home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 / Ham Radio 2000.iso / ham2000 / qex / hdlant21 / hdlant21.cpp < prev    next >
C/C++ Source or Header  |  1996-04-01  |  87KB  |  2,984 lines

  1. // HDL_ANT2.CPP     copyright 1994,1995,1996 Paul Wade N1BWT
  2. // version 2.1e   1 April 1996
  3. // 2.1 fixes precision problem
  4. // e version for the metric-impaired
  5. //
  6. //      Any licensed radio amateur may use this program without 
  7. //      charge; all other persons must send $73 to the 
  8. //      ARRL Foundation, 225 Main St., Newington, CT 06111
  9.  
  10. //The source file, HDL_ANT2.CPP, was compiled using Borland C++
  11. //version 4.0.  Any part of it may be modified or used as part
  12. //of another program by any amateur radio operator, provided
  13. //that credit is given and provided there is no charge for
  14. //its use.
  15.  
  16. //Send problems, suggestions, and comments to Paul Wade, N1BWT.
  17. //Expect support commensurate with the cost of the program!
  18.  
  19. //antenna.h - header file for antenna.cpp
  20. //
  21. // N1BWT 1994
  22. // compiled with Borland C++ version 3.1
  23. // 1995 Borland C++ version 4.0
  24.  
  25. #include <math.h>
  26. #include <iostream.h>
  27. #include <fstream.h>
  28. #include <iomanip.h>
  29. #include <ctype.h>
  30. #include <strstrea.h>
  31. #include <string.h>
  32. #include <bios.h>
  33. //#include <constrea.h>
  34. #include <conio.h>
  35.  
  36.  
  37. #include <ps.h>         // PostScript commands
  38.  
  39.  
  40. #define LINESIZE 1024
  41. #define CTRL_C 0x2e03
  42. #define UP_ARROW 0x4800
  43. #define DOWN_ARROW 0x5000
  44. #define HOME_KEY 0x4700
  45. #define END_KEY 0x4f00
  46. #define ENTER_KEY 0x1c0d
  47.  
  48.  
  49.  
  50. // global constants
  51.     const double c = 299792456.0;     //  meters per second 
  52.     const double pi = 3.1415927 ;
  53.     const double crad = 57.29578 ;
  54.  
  55. // other globals
  56.     
  57.     int lib_init = 1;        /* if lib_init, then we need to initialize
  58.                    the library routines */
  59.     int ph_init = 1;
  60.  
  61.     char *units = " mm.  ";
  62.  
  63.     float metric = 1.0;
  64.  
  65.     char *unit_type = "Metric ";
  66. //
  67.  
  68.  
  69.  
  70.  
  71.  
  72.  
  73. // start of ANTENNA.H - class declarations
  74.  
  75. class Antenna           // Abstract base class
  76. {
  77. public:
  78.     Antenna();
  79.     void helpscreen();
  80.     void get_freq();
  81.     void get_wg();
  82.     void horn_dimensions();
  83.     void horn_calcgain();
  84.     void horn_phasecenters();
  85.     void horn_angles();
  86.     void G3RPE_approximation(double);
  87.     void banner(ostream&);
  88.     void info_listing(ostream&);
  89.     void post_print(ostream&);
  90.     void PANFI_corr();
  91.     void range_calc();
  92.     void sun_gnd_NF();
  93.     void check_aperture();
  94.     double get_fod() {return fod;};
  95.     double get_wl() {return wavelength;};
  96.     int bad_input() {return bad;};
  97.  
  98.     double wavelength;          // in mm */
  99.       
  100. protected:
  101.     double freq;      
  102.     double H_wg;                // waveguide H dim. in mm. */ 
  103.     double E_wg;                // waveguide E dim. in mm. */ 
  104.     double axial_length;        // axial length of feed horn flare in mm */
  105.     double H_aperture;          // horn E-Plane aperture in mm */ 
  106.     double E_aperture;          // horn H-Plane aperture in mm */ 
  107.     double horn_gain;       
  108.     double E_phase_center;
  109.     double H_phase_center;
  110.     double E_flare_angle;       // angle from axis to E-side
  111.     double H_flare_angle;       // angle from axis to H-side
  112.     double E_side;
  113.     double E_ang;
  114.     double H_side;
  115.     double H_ang;
  116.     double aperture;
  117.     double efficiency;
  118.     double rayleigh_dist;
  119.     double directivity;
  120.     double fod;
  121.     int bad;                    // problem with input
  122. };
  123.  
  124.  
  125. class Horn : public Antenna
  126. {
  127. public:
  128.     Horn();
  129.     void lookup();
  130.     void simple_gain();
  131.     void coords();
  132.     void PS_template();
  133.     void write_data(ostream&, int);
  134.         
  135. private:
  136.  
  137.     double simplegain;       
  138.     Point inner[6];
  139.     Point outer[6];
  140.  
  141. };
  142. //
  143.  
  144.  
  145.  
  146.  
  147.  
  148.  
  149.  
  150. class Dish : public Antenna
  151. {
  152. public:
  153.     Dish();
  154.     void d_init();
  155.     void illumination();
  156.     void calc_gain();
  157.     void phasecenters();
  158.     void PS_template();
  159.  
  160.     
  161. private:
  162.                 // all dimensions in mm.
  163.     double freq;
  164.     double diameter;                
  165.     double depth;                   // at center of dish
  166.     double focal_length;        
  167.     double f_over_D;
  168.     double feedangle;               // diameter subtended angle from focal point
  169.     double feedang_deg;
  170.     double R_edge;                  // distance from focal point to edge
  171.     double space_attn;
  172.     double desired_taper;
  173.     double BW3;                     // 3 dB beamwidth
  174.     double simple_horn_diameter;
  175.     double dish_gain;                 
  176. };
  177.  
  178.  
  179. class OffsetDish : public Antenna
  180. {
  181. public:
  182.     OffsetDish();
  183.     void offset_init();
  184.     void offset_illumination();
  185.     void offset_calc_gain();
  186. //    void phasecenters();
  187. //    void PS_template();
  188.     
  189. private:
  190.                 // all dimensions in mm.
  191.     double freq;
  192.     double diameter;                
  193.     double small_diameter;          // small axis of oval offset reflector   
  194.     double large_diameter;          // large axis of oval offset reflector      
  195.     double depth;                   // at center of full parabola
  196.     double odepth;                  // deepest point in offset reflector
  197.     double odepth_position;         // distance across rim to deepest pt.
  198.     double tilt_angle;
  199.     double focal_length;        
  200.     double equiv_f_over_D;          // focal length over small diameter
  201.     double f_over_D;
  202.     double feedangle;               // diameter subtended angle from focal point
  203.     double feedang_deg;
  204.     double small_feedangle;         // in plane of small axis
  205.     double small_feedang_deg;       
  206.     double large_feedangle;         // in plane of large axis   
  207.     double large_feedang_deg;          
  208.     double R_edge;                  // distance from focal point to edge
  209.     double R_aim;                   // distance from focal point to aiming pt.
  210.     double space_attn;
  211.     double desired_taper;
  212.     double BW3;                     // 3 dB beamwidth
  213.     double simple_horn_diameter;
  214.     double dish_gain;                 
  215.  
  216. };
  217.  
  218. class Lens : public Antenna
  219. {
  220.  
  221. public:
  222.     Lens();
  223.     void dimension();    
  224.     void calculate();
  225.     void phasecheck();
  226.     void plates();
  227.     void write_data(ostream &, int);
  228.     void crude_graphics(ostream &);
  229.     
  230. private:
  231.  
  232.     double Lens_diam ;       /* Lens diameter in mm */
  233.     double spacing   ;       /* metal plate spacing in mm */
  234.     double width_increase ;  /* plates get wider toward edge */
  235.     double shift[25];        /* H-plane phase compensation */
  236.     int N ;                  /* number of plates in lens */
  237.     double BW_E_horn ;           /* feed horn E-plane Beamwidth in degrees */
  238.     double lens_focal_length ;   /* in mm */
  239.     double Gain_lens ;           /* dB added by lens */
  240.     double index ;               /* effective index of refraction */
  241.     double lens_to_horn;        // horn mouth to lens curve center in mm.
  242.     double step;                // step distance in zoned lens plate */
  243.     int compensate ;            // flag for phase center compensation needed
  244. };
  245.  
  246. // end of ANTENNA.H - class declarations
  247.  
  248. //
  249.  
  250.  
  251.  
  252.  
  253.  
  254.  
  255. // start of ANTENNA.CPP - class member functions
  256.  
  257.   
  258. Antenna::Antenna()              // Constructor
  259. {
  260.     freq = 0.0;      
  261.     H_wg = 0.0; 
  262.     E_wg = 0.0;
  263.     wavelength = 0.0;
  264.     horn_gain = 0.0;        
  265.     axial_length = 0.0;
  266.     H_aperture = 0.0;
  267.     E_aperture = 0.0;   
  268.     H_flare_angle = 0.0;
  269.     E_flare_angle = 0.0;
  270.     E_side = 0.0;
  271.     E_ang = 0.0;
  272.     H_side = 0.0;
  273.     H_ang = 0.0;
  274.     aperture = 0.0;
  275.     efficiency = 0.0;
  276.     rayleigh_dist = 0.0;
  277.     directivity = 0.0;
  278.     bad = 0;
  279. }
  280.  
  281. void Antenna::banner(ostream& ostrm)
  282. {  /* a banner */
  283.         
  284.     ostrm << "\n\n\n\n";
  285.     ostrm << "             ***************** \n";
  286.     ostrm << "             *               * \n";
  287.     ostrm << "             *    HDL_ANT    * \n";
  288.     ostrm << "             *  version 2.1  * \n";
  289.     ostrm << "             *               * \n";
  290.     ostrm << "             ***************** \n";
  291.     ostrm << "\n       copyright 1994,1995,1996 Paul Wade N1BWT \n\n";
  292.     ostrm << "      Version 2.1 with option for the metric-impaired\n";
  293.     ostrm << "      -> fixes roundoff error problem with Version 2.0.\n\n";
  294.     ostrm << "      Any licensed radio amateur may use this program "
  295.           << "without \n";
  296.     ostrm << "      charge; all other persons must send $73 to the \n";
  297.     ostrm << "      ARRL Foundation, 225 Main St., Newington, CT 06111";
  298.     ostrm << "\n\n";
  299. }
  300.  
  301. void Antenna::info_listing(ostream& ostrm)
  302. {
  303.  
  304. ostrm << "HDL_ANT does the calculations needed to successfully implement\n";
  305. ostrm << "several microwave antennas: horns, parabolic dishes, and \n";
  306. ostrm << "metal-plate lenses.  It also does the calculations involved in\n";
  307. ostrm << "setting up an antenna range for antenna gain measurement.  More\n";
  308. ostrm << "detailed explanations of the antennas and measurements may be\n";
  309. ostrm << "found in the series of QEX articles entitled 'Practical Microwave\n";
  310. ostrm << "Antennas,' in the September, October, and November 1994 issues.\n\n";
  311.  
  312. ostrm << "An additional article, 'More on Parabolic Dish Antennas,' in the\n";
  313. ostrm << "December 1995 issue of QEX, gave the descriptions for Offset \n";
  314. ostrm << "dishes, Penny feeds, and the use of sun noise to measure antenna\n";
  315. ostrm << "performance and receiver noise figure.\n\n";
  316.  
  317. ostrm << "All dimensions are in millimeters, since one mm. is about the \n";
  318. ostrm << "accuracy required for antennas to work well at 10 GHz.\n";
  319. ostrm << "However, there is an option for dimensions in inches, for the\n";
  320. ostrm << "metric-impaired.\n\n";
  321.  
  322. ostrm << "MENU CHOICES:\n\n";
  323. ostrm << "  H\n\n";
  324.  
  325. ostrm << "For horn antennas, HDL_ANT will design an 'optimum' horn with \n";
  326. ostrm << "a specified gain (between 10 and 25 dB) for any frequency - use \n";
  327. ostrm << "menu entry 'H' for this option.  It will then create a PostScript\n";
  328. ostrm << "template file which may be used to print a paper template for\n";
  329. ostrm << "horn construction.  The paper template is attached to a sheet of\n";
  330. ostrm << "copper or brass which is cut and folded on the template lines,\n";
  331. ostrm << "then soldered together and soldered to a waveguide.\n\n";
  332. ostrm << "See menu entry 'P' for more details on printing a "
  333.       << "PostScript file.\n\n";
  334.  
  335. ostrm << "  E\n\n";
  336.  
  337. ostrm << "Menu entry 'E' is used to calculate the gain and other parameters\n";
  338. ostrm << "for an existing horn - perhaps one you found at a hamfest.  It \n";
  339. ostrm << "can also create a template, to duplicate a horn known to have\n";
  340. ostrm << "good dimensions.\n\n";
  341.  
  342. ostrm << "  D\n\n";
  343.  
  344. ostrm << "Parabolic dish calculations are under menu entry 'D'.  The most\n";
  345. ostrm << "important dish dimension is the focal length, and the easiest way\n";
  346. ostrm << "to find it is to measure the depth of the dish in the center,\n";
  347. ostrm << "measured from a straightedge across the rim of the dish.  HDL_ANT\n";
  348. ostrm << "then calculates the focal length and f/D ratio, to allow\n";
  349. ostrm << "selection of the best feed antenna - see the QEX series for\n";
  350. ostrm << "details on feedhorn selection.  For smaller dishes, HDL_ANT can\n";
  351. ostrm << "also generate a PostScript template file;  the printed template\n";
  352. ostrm << "is used to check the accuracy of the parabolic curve of the dish.\n";
  353. ostrm << "If it is not a good fit, sometimes a template for a slightly\n";
  354. ostrm << "larger or smaller f/D ratio gives a better fit, since dishes\n";
  355. ostrm << "sometimes have a flat area or large hole in the center which\n";
  356. ostrm << "yields a misleading depth measurement.\n\n";
  357.  
  358. ostrm << "  L\n\n";
  359.  
  360. ostrm << "Menu entry 'L' is used to design metal-plate lens antennas.\n";
  361. ostrm << "These are normally fed by a horn; if an appropriate horn is not\n";
  362. ostrm << "already available, then the 'H' entry may be used to design the\n";
  363. ostrm << "horn.  It may take a few trials to find a good combination of\n";
  364. ostrm << "horn and lens.  Note that the 'optimum' horns designed under the\n";
  365. ostrm << "'H' entry of the HDL_ANT program do not usually have the matched\n";
  366. ostrm << "E-plane and H-plane phase centers needed for good lens\n";
  367. ostrm << "performance; some adjustment of horn dimensions can improve the\n";
  368. ostrm << "phase center matching.  The lens design does not create templates\n";
  369. ostrm << "since the lens curves are all simple circles which can be drawn\n";
  370. ostrm << "more accurately with a compass.\n\n";
  371.  
  372. ostrm << "  R\n\n";
  373.  
  374. ostrm << "Antenna range design is selected by menu entry 'R'.  HDL_ANT\n";
  375. ostrm << "calculates the minimum length and measurement height required for\n";
  376. ostrm << "a specified maximum antenna aperture, and then calculates the\n";
  377. ostrm << "height of the source antenna needed to have the RF field peak at\n";
  378. ostrm << "the measurement height.\n\n";
  379.  
  380. ostrm << "  C\n\n";
  381.  
  382. ostrm << "If a noise figure meter is used to measure antenna gain as\n";
  383. ostrm << "described in the November 1994 QEX article, then it is necessary\n";
  384. ostrm << "to convert noise figure readings into antenna gain.  \n";
  385. ostrm << "Menu entry 'C' makes these calculations.\n\n";
  386.  
  387. ostrm << "  P\n\n";
  388.  
  389. ostrm << "Menu entry 'P' is a short explanation of how to print PostScript\n";
  390. ostrm << "files.\n\n";
  391.  
  392. ostrm << "  I\n\n";
  393.  
  394. ostrm << "Menu entry 'I' is this summary of information about HDL_ANT.\n\n";
  395.  
  396. ostrm << "  U\n\n";
  397.  
  398. ostrm << "Menu entry 'U' allows you to select dimensions in either\n" 
  399.       << "millimeters or inches.  HDL_ANT defaults to millimeters.\n\n";
  400.  
  401. ostrm << "  O\n\n";
  402.  
  403. ostrm << "Menu entry 'O' is a new feature for version 2.0 which does\n"
  404.       << "calculations for oval-shaped offset-fed parabolic reflectors.\n"
  405.       << "This routine uses a curve-fitting algorithm to find the focal\n"
  406.       << "point and tilt angle for aiming the dish.  Required input data\n"
  407.       << "are the dimensions of the large and small axis of the oval, and\n"
  408.       << "the depth and location of the deepest point in the reflector,\n"
  409.       << "measured along a straightedge placed across the rim on the large\n"
  410.       << "axis.\n\n"
  411.       << "For offset reflectors that are not oval shaped, please read my\n"
  412.       << "article in QEX, December, 1995 on offset dishes for suggestions.\n\n";
  413. ostrm << "There is an option to design a rectangular feedhorn as descibed\n"
  414.       << "in Menu entry 'F'.\n\n";      
  415.  
  416. ostrm << "  F\n\n";
  417.  
  418. ostrm << "Menu entry 'F' is a new feature for version 2.0 which will\n"
  419.       << "design a rectangular feedhorn for a dish with a specified f/D\n"
  420.       << "using a straightline approximation to the G3RPE curves.  The\n"
  421.       << "approximation is accurate to about 2% for f/D < 0.8, and about\n"
  422.       << "6% for larger f/D. It will then create a PostScript\n";
  423. ostrm << "template file which may be used to print a paper template for\n";
  424. ostrm << "horn construction as described for Menu Entry 'H'.  \n\n";
  425. ostrm << "The feedhorn dimensions generated by the approximation do not\n";
  426. ostrm << "necessarily have equal E- and H-plane phase centers, so you may\n";
  427. ostrm << "need to adjust the axial length of the horn to find a length that\n";
  428. ostrm << "matches the phase centers to within 0.1 wavelengths without \n";
  429. ostrm << "reporting any errors in the phase center routines.\n\n";
  430. ostrm << "Also, the feedhorn dimensions assume a reflector which has\n";
  431. ostrm << "symmetrical illumination angles in both planes.  For reflectors\n";
  432. ostrm << "requiring assymetrical illumination, run this option once for each\n";
  433. ostrm << "illumination angle ( or equivalent f/D ), note the dimensions, \n";
  434. ostrm << "and adjust the horn dimensions to use the appropriate one in each \n";
  435. ostrm << "plane.  Make sure the E-plane matches the normal polarization,\n";
  436. ostrm << "i.e., E-plane horizontal for horizontal polarization, or E-plane\n";
  437. ostrm << "vertical for vertical polarization.\n\n";
  438.  
  439.  
  440.  
  441. ostrm << "  N\n\n";
  442.  
  443. ostrm << "Menu entry 'N' is a new feature for version 2.0 which calculates\n"
  444.       << "receiver noise figure by comparing noise received from \n"
  445.       << "cold sky and warm ground.\n\n:";
  446.  
  447. ostrm << "  Q\n\n";
  448.  
  449. ostrm << "'Q' for Quit ends the program.\n\n\n";
  450.  
  451.  
  452. ostrm << "The source file, HDLANT21.CPP, was compiled using Borland C++ \n";
  453. ostrm << "version 4.0.  Any part of it may be modified or used as part\n";
  454. ostrm << "of another program by any amateur radio operator, provided\n";
  455. ostrm << "that credit is given and provided there is no charge for\n";
  456. ostrm << "its use.\n\n";
  457.  
  458. ostrm << "Send problems, suggestions, and comments to Paul Wade, N1BWT.\n";
  459. ostrm << "Expect support commensurate with the cost of the program!\n";
  460. }
  461.  
  462. void Antenna::post_print(ostream& ostrm)
  463. {
  464. ostrm << "\n            PRINTING POSTSCRIPT[tm] FILES\n\n";
  465.         
  466. ostrm << "      The easiest way to print PostScript files is with a \n";
  467. ostrm << "      PostScript compatible laser printer.  These have become\n";
  468. ostrm << "      more affordable and are becoming more common; for\n";
  469. ostrm << "      instance, the public library in my small town has one\n";
  470. ostrm << "      attached to a public-access computer.   However, they are\n";
  471. ostrm << "      still roughly twice as expensive as the dot-matrix\n";
  472. ostrm << "      printers that most of us use with our personal computers.\n";
  473. ostrm << "      \n";
  474. ostrm << "      An alternative to a laser printer is software that\n";
  475. ostrm << "      interprets PostScript language commands for display on a\n";
  476. ostrm << "      computer VGA display or a dot-matrix printer.  I know of\n";
  477. ostrm << "      several versions of this type of software:  GoScript, a\n";
  478. ostrm << "      commercial product, Ultrascript, a commercial product,\n";
  479. ostrm << "      Freedom of Press , a commercial product, and Ghostscript,\n";
  480. ostrm << "      [Copyright (C) 1990, 1992 Aladdin Enterprises.  All\n";
  481. ostrm << "      rights reserved.  Distributed by Free Software\n";
  482. ostrm << "      Foundation, Inc.], which is freeware.  \n";
  483. ostrm << "      \n";
  484. ostrm << "      I have only used Ghostscript, version 2.5.  While 286,\n";
  485. ostrm << "      386, and windows versions are available, the 286 version\n";
  486. ostrm << "      seems to work most reliably even on a 386 or 486 PC.  It\n";
  487. ostrm << "      uses Unix style command strings which are difficult to\n";
  488. ostrm << "      remember, so I've included two BAT files to help:\n";
  489. ostrm << "      GS_VIEW.BAT for viewing on a screen, and GS_PRINT.BAT for\n";
  490. ostrm << "      printing on an Epson dot-matrix printers.  For other\n";
  491. ostrm << "      brands of printer, the command will have to be changed\n";
  492. ostrm << "      appropriately, which will require reading of the\n";
  493. ostrm << "      documentation.  Type GS_VIEW <filename.ps> or GS_PRINT\n";
  494. ostrm << "      <filename.ps> to use them.  Be sure to type QUIT when you\n";
  495. ostrm << "      are through or your PC may be left in an unhappy state\n";
  496. ostrm << "      requiring rebooting.  \n";
  497. ostrm << "      \n";
  498. ostrm << "      I've also included a sample PostScript file, SQUARE.PS,\n";
  499. ostrm << "      which draws a four inch square to make sure that\n";
  500. ostrm << "      templates will be drawn to scale, and a sample horn\n";
  501. ostrm << "      template, HORN18.PS, to get you started.  If the\n";
  502. ostrm << "      dimensions of the printed square are slightly off, you\n";
  503. ostrm << "      can correct them.  Each template has a line near the\n";
  504. ostrm << "      beginning of the file:\n";
  505. ostrm << "      \n";
  506. ostrm << "              1.0 1.0 scale\n";
  507. ostrm << "              \n";
  508. ostrm << "      the first number is the scale factor in the x\n";
  509. ostrm << "      (horizontal) direction, and the second is the scale\n";
  510. ostrm << "      factor in the y (vertical) direction.  Edit the SQUARE.PS\n";
  511. ostrm << "      file with an editor to change these numbers slightly;\n";
  512. ostrm << "      when you find a combination that prints a square exactly\n";
  513. ostrm << "      four inches on a side, then you have compensated for your\n";
  514. ostrm << "      printer.  Edit these same numbers into any template to be\n";
  515. ostrm << "      printed on the same printer and the dimensions will come\n";
  516. ostrm << "      out right.\n";
  517. ostrm << "      \n";
  518. ostrm << "      The Ghostscript files are available on many bulletin\n";
  519. ostrm << "      boards and Internet locations.  They are in ZIP format,\n";
  520. ostrm << "      so they must me downloaded, unZIPped, and installed\n";
  521. ostrm << "      according to the README documentation.\n";
  522. ostrm << "      \n";
  523. ostrm << "      I have not used any of the commercial products, but I\n";
  524. ostrm << "      would expect a commercial product to be much easier to\n";
  525. ostrm << "      install and use than freeware or shareware.   \n";
  526. ostrm << "      \n";
  527. ostrm << "      The batch files are as follows:\n\n";
  528. ostrm << "GS_VIEW.BAT\n\n";
  529. ostrm << "   gs %1\n\n";
  530. ostrm << "GS_PRINT.BAT\n\n";
  531. ostrm << "   gs -sDEVICE=epson -r60x60 %1\n";
  532. }
  533.  
  534. void Antenna::PANFI_corr()
  535. {
  536. // correction for PANFI readings to Antenna Gain
  537.  
  538.     float Tex_dB;  // Excess noise calibration
  539.  
  540.     cout << "\nPANFI calibration setting - Excess noise in dB: " ;
  541.     cout.flush();
  542.     cin >> Tex_dB;
  543.  
  544.     float std_db;
  545.      cout << "\nGain of standard gain antenna: " ;
  546.     cout.flush();
  547.     cin >> std_db;
  548.     cout << "\n\n";
  549.  
  550.     double nf = 0.0;   // indicated noise figure in dB
  551.  
  552.     cout << "Enter a negative Noise Figure to return to Main Menu\n\n\n";
  553.  
  554.     while (nf >= 0.0)
  555.     {
  556.         double std_nf;
  557.         cout << "\nIndicated Noise Figure for Standard gain antenna: " ;
  558.     cout.flush();
  559.     cin >> std_nf ;
  560.  
  561.         double ratio = pow(10.0,(0.1 * (Tex_dB - std_nf)));
  562.         double Y_std = 10.0 * log10( 1.0 + ratio);
  563.         cout << setprecision(3) 
  564.          << "\n            Y factor = " << Y_std <<  " dB\n\n";
  565.  
  566.         cout << "\nIndicated Noise Figure for antenna under test: " ;
  567.     cout.flush();
  568.     cin >> nf ;
  569.  
  570.         ratio = pow(10.0,(0.1 * (Tex_dB - nf)));
  571.         double Y_db = 10.0 * log10( 1.0 + ratio);
  572.  
  573.         cout << setprecision(3) 
  574.          << "\n           Y factor = " << Y_db <<  " dB\n\n";
  575.  
  576.  
  577.     double G_db = Y_db - Y_std + std_db;
  578.     cout << setprecision(3)
  579.          << "      Corrected gain = " << G_db <<  " dBi\n\n";
  580.  
  581.     float dia;
  582.     cout << "Aperture diameter in " << units << ": " ;
  583.     cout.flush();
  584.     cin >> dia ;
  585.         dia *= metric;
  586.  
  587.         double g_ratio = pow(10.0,(0.1 * G_db));
  588.  
  589.         directivity = pi * pi * dia * dia /( wavelength * wavelength);
  590.  
  591. //cout << "Directivity = " << directivity;
  592.  
  593.         efficiency = g_ratio / directivity;
  594.                 
  595.         cout << setprecision(2) 
  596.              << "\n\n      Aperture efficiency = " << (efficiency * 100) 
  597.              <<  " %\n\n\n";        
  598.     }
  599. }
  600.  
  601.  
  602. void Antenna::range_calc()
  603. {
  604. // calculations for Antenna Range design
  605. // this routine returns feet or meters so has hard constants
  606.  
  607.     cout << "\nLargest aperture diameter to be measured, in "
  608.          << units << ": ";
  609.     cout.flush();
  610.     cin >> aperture;
  611.     
  612.     aperture *= metric;
  613.  
  614.     rayleigh_dist = 2.0 * aperture * aperture / wavelength;
  615.  
  616.     float big_u;
  617.     char *big_units = "xxxxxx";
  618.  
  619.     if (metric == 1.0)
  620.     {
  621.         big_u = 1000.0;
  622.         big_units = "meters";
  623.     }
  624.     else
  625.     {
  626.         big_u = 304.8;
  627.         big_units = "feet  ";
  628.     }
  629.         
  630.      cout << "\n\nRayleigh distance (minimum range length) = "
  631.           << setprecision(3) << (rayleigh_dist / big_u) << " "
  632.           << big_units << "\n\n";
  633.  
  634.      cout << "Suggested measurement height = "
  635.           << setprecision(3) << (aperture * 4.0 / big_u) << " "
  636.           << big_units << "\n\n";
  637.  
  638.     double range_length;
  639.     cout << "Enter desired range length in " << big_units << ": ";
  640.     cout.flush();
  641.     cin  >> range_length;
  642.     
  643.     range_length *= big_u;      // mm.
  644.     
  645.     if (range_length < rayleigh_dist)
  646.         cout << "\n\nWARNING - range too short for "
  647.              << "accurate gain measurement\n\n";
  648.  
  649.         double meas_height;
  650.         cout << "\n\nEnter desired measurement height in "
  651.              << big_units << ": ";
  652.         cout.flush();
  653.         cin  >> meas_height;
  654.              
  655.         meas_height *= big_u;      // mm.
  656.     
  657.     if (meas_height < (3.2 * aperture))
  658.         cout << "\n\nWARNING - measurement height insufficient for "
  659.              << "accurate gain measurement\n\n";
  660.  
  661.     double source_height = wavelength * range_length / (4.0 * meas_height);
  662.     
  663.     cout << "\n\nHeight of source antenna should be "
  664.          << setprecision(4) << (source_height / metric) << " "
  665.          << units << " \n\n";
  666. }
  667.  
  668.  
  669. void Antenna::sun_gnd_NF()
  670. {
  671. // calculate NF from sun and ground noise as hot and cold sources
  672.  
  673.     double Tsky;    
  674.     cout << "\nEnter temperature of cold sky in K: " ;
  675.     cout.flush();
  676.     cin >> Tsky;
  677.  
  678.     float Tground;
  679.     if (metric > 1.0)
  680.     {
  681.         cout << "\nEnter temperature of ground in degrees Fahrenheit: " ;
  682.         cout.flush();
  683.         cin >> Tground;
  684.         Tground = 273.0 + ((Tground - 32.0) / 1.8);
  685.     }
  686.     else
  687.     {
  688.         cout << "\nEnter temperature of ground in K: " ;
  689.         cout.flush();
  690.         cin >> Tground;
  691.     }
  692.     cout << "\n\n";
  693.  
  694.     double Te;          // receiver noise figure
  695.     double nf_db;
  696.  
  697.     double Y_db = 0.0;  // measured Y-factor in dB
  698.     double Y_factor ;        
  699.  
  700.     cout << "Enter a negative Y-factor to return to Main Menu\n\n\n";
  701.  
  702.     cout << "\nEnter Y-factor (difference between sky and ground) in dB: ";
  703.     cout.flush();
  704.     cin >> Y_db;
  705.  
  706.  
  707.      while (Y_db > 0.0)
  708.     {
  709.  
  710.  
  711.         Y_factor = pow(10.0,(0.1 * Y_db));
  712.  
  713.         Te = (Tground - Y_factor * Tsky) / (Y_factor -1.0);
  714.         
  715.         nf_db = 10.0 * log10((Te / 290.0) + 1.0); 
  716.  
  717.         cout << setprecision(4) 
  718.           << "\n    Receiver Noise temperature = " << Te <<  " K\n\n";
  719.  
  720.         cout << setprecision(3) 
  721.          << "\n    Receiver Noise figure = " << nf_db <<  " dB\n\n";
  722.  
  723.         cout << "\nEnter Y-factor (difference between sky and ground) in dB: ";
  724.         cout.flush();
  725.     cin >> Y_db;
  726.  
  727.     }
  728. }
  729.  
  730.  
  731. //
  732.  
  733.  
  734.  
  735.  
  736. Dish::Dish() : Antenna()
  737. {               // constructor 
  738.     freq = 0.0;                 
  739.     diameter = 0.0;             
  740.     depth = 0.0;                
  741.     focal_length = 0.0;         
  742.     f_over_D = 0.0;             
  743.     feedangle = 0.0;            
  744.     feedang_deg = 0.0;          
  745.     R_edge = 0.0;                    
  746.     space_attn = 0.0;           
  747.     desired_taper = 0.0;        
  748.     BW3 = 0.0;                  
  749.     simple_horn_diameter = 0.0; 
  750.     wavelength = 0.0;           
  751.     dish_gain = 0.0;                 
  752.     
  753. }
  754.  
  755. void Dish::d_init()
  756. {
  757.     cout << "\nDiameter of dish in " << units << ": " ;
  758.     cout.flush();
  759.     cin >> diameter ;
  760.     diameter *= metric;   //mm
  761.  
  762.     char mode = 'n';
  763.     cout << "\nDo you know the f/D ratio [Yes or No]?  ";
  764.     cout.flush();
  765.     cin >> mode ;
  766.     mode = toupper(mode);
  767.  
  768.     if (mode == 'Y')
  769.     {
  770.         cout << " \n Enter f/D ratio: ";
  771.     cout.flush();
  772.     cin >> f_over_D;
  773.  
  774.     focal_length = f_over_D * diameter ;
  775.     }
  776.     else
  777.     {
  778.     cout << " \n Enter Depth of dish in " << units << ": " ;
  779.     cout.flush();
  780.     cin >> depth;
  781.         depth *= metric;      //mm
  782.  
  783.     focal_length = (diameter * diameter) / ( 16.0 * depth);
  784.     f_over_D = focal_length / diameter ;
  785.  
  786.     cout << "\n\n     f/D = " << setprecision(2) << f_over_D << "\n" ;
  787.     }
  788.  
  789.     cout << "\nFocal length = "
  790.          << setprecision(4) <<  (focal_length / metric) 
  791.          << " " << units << endl;
  792.  
  793. }
  794.  
  795. void Dish::illumination()
  796. {
  797.     feedangle = 2 * atan2(1.0,((2.0 * f_over_D) - (1.0/(8.0 * f_over_D))));
  798.     feedang_deg = crad * feedangle ;   // degrees conversion
  799.  
  800.         // R_edge = distance from focal point to edge
  801.  
  802.     R_edge = 2.0 * focal_length / ( 1 + cos(feedangle/2.0));
  803.  
  804.         // Space_attn is additional path loss to edge of dish
  805.     double Space_attn = (20.0 * log10(R_edge / focal_length));
  806.  
  807.         // Desired_taper to achieve 10 dB actual edge taper
  808.     double Desired_taper = 10.0 - Space_attn;  // dB
  809.  
  810.     BW3 = feedangle * sqrt( 3.0 / Desired_taper) ;
  811.  
  812.     double Simple_horn_diameter = 66.0 / (BW3 * crad) ; // wavelengths
  813.  
  814.     cout << "\n\n  Illumination angle for feed = "
  815.          << setprecision(3) <<  feedang_deg << " degrees";
  816.  
  817.     cout << "\n  Space attenuation = "
  818.          << setprecision(2) << Space_attn << " dB ";
  819.     cout << "\n  Desired taper = "
  820.          << setprecision(2) << Desired_taper << " db "
  821.          << "for 10 dB edge illumination";
  822.  
  823.     cout << "\n\nA simple feed horn would have a diameter of "
  824.          << setprecision(2) << Simple_horn_diameter << " wavelengths";
  825.  
  826.     cout << "\n   for a 3 dB beamwidth of "
  827.          << setprecision(3) << (BW3 * crad) << " degrees\n";
  828.  
  829.  
  830. //        Write_PS(diameter, focal_length);
  831.  
  832. }
  833.  
  834. void Dish::calc_gain()
  835. {
  836.     efficiency = 0.5;     // assume 50% efficiency
  837.  
  838.     double radius = 0.5 * diameter;
  839.  
  840.     aperture = pi * radius * radius;
  841.  
  842.     dish_gain = efficiency * aperture * 4.0 * pi / (wavelength * wavelength);
  843.  
  844.     dish_gain = 10.0 * log10(dish_gain);
  845.  
  846.     cout << "\nGain at 50% efficiency = " << setprecision(3) << dish_gain
  847.      << " dBi \n";
  848. }
  849.  
  850.  
  851. void Dish::PS_template()
  852. {                      // PostScript template on one page
  853.  
  854.     char descriptor[LINESIZE] = " ";
  855.     char outname[LINESIZE];
  856.  
  857.     cin.ignore(LINESIZE,'\n');
  858.     cout << " Dish description line: ";
  859.     cout.flush();
  860.     cin.get(descriptor,LINESIZE,'\n');
  861.  
  862.     cout << "File name for dish template (should be .PS ): ";
  863.     cout.flush();
  864.     cin >> outname ;
  865.  
  866.     ofstream outfil(outname);
  867.  
  868.     if (!outfil)
  869.     {
  870.     cerr << "Cannot open output file for output";
  871.     }
  872.  
  873. // header
  874.  
  875.     outfil << "%! PostScript\n";
  876.  
  877.     outfil << "% template for " << (diameter/metric) 
  878.            << " " << units << " parabolic dish\n";
  879.     outfil << "% with f/d = " << f_over_D << " and focal length = "
  880.            << (focal_length/metric) << " " << units << "\n";
  881.     
  882.     outfil << "% generated by HDLANT21 by N1BWT 1994,1995,1996 \n";
  883.     outfil << "%\n";
  884.     outfil << "%" << descriptor;
  885.     outfil << "%\n";
  886.     outfil << "% Print on PostScript printer\n";
  887.     outfil << "% cut along the curve,\n";
  888.     outfil << "% and use it as a template for the dish.\n\n\n";
  889.     
  890.     outfil << "%\n";
  891.     outfil << "/in { 72 mul } def\n";
  892.     outfil << "/mm { 2.834646 mul } def\n";
  893.  
  894.     outfil << "%\n";
  895.     outfil << "% 100% scaling factors - change for printer correction\n";
  896.     outfil << "1.0 1.0 scale \n";
  897.     outfil << "%\n";
  898.  
  899. outfil << "% DISH **********************************************\n\n";
  900.  
  901. //    Point offset =  Point(50.0,(100.0 - (diameter/4.0))) ;
  902.     Point offset =  Point(50.0, 260.0);
  903.  
  904.     outfil << offset.x() << " mm " << offset.y() << " mm translate" << endl;
  905.  
  906.     outfil << "% DISH\n";
  907. outfil << "gsave\n";
  908.  
  909. // and dish outline 
  910.  
  911. // NOTE: I'm doing this directly in picas, so can't use PS_lineto
  912.         
  913.     int prad = int(2.834636 * diameter / 2.0);         // radius in picas 
  914.     double pa = 4.0 * focal_length * 2.834636;       // 4 * f in picas 
  915.         
  916.     outfil << "newpath\n";
  917.  
  918.     outfil << PS_moveto() << endl;
  919.         
  920.     double i_d;    
  921.     double curvature;
  922.     for ( int i = 0; i <= prad; i++)
  923.     {
  924.         i_d = (double)i;
  925.         curvature = i_d * i_d / pa ;
  926.         outfil << curvature << " " << (-i) << " lineto\n";   // draw it vertically
  927.     }
  928.     outfil << "stroke \n\n";
  929.             
  930. // and draw a box around it 
  931.  
  932.     outfil << "newpath\n";
  933.     outfil << curvature << " " << (-prad) << " moveto" << endl;
  934.     outfil << curvature << " 0 lineto " << endl;
  935.     outfil << "0 0 lineto " << endl;
  936.     outfil << "0 " << (-prad) << " lineto" << endl;
  937.     outfil << curvature << " " << (-prad) << " lineto" << endl;
  938.     outfil << "stroke\n";    
  939.  
  940. // Text
  941.     outfil << "/Helvetica-Bold findfont\n";
  942.     outfil << "14 scalefont\n";
  943.     outfil << "setfont\n";
  944. // position title
  945.  
  946.     outfil << "-25 mm -25 mm moveto\n";
  947.     outfil << "(Template for " << diameter << "mm dish with f/d = " 
  948.            << f_over_D << " ) show\n";
  949.     outfil << "-25 mm  -35 mm moveto\n";
  950.     outfil << " (N1BWT 1994) show \n";
  951.  
  952.  
  953.     outfil << "% END DISH **********************************************\n";
  954.     outfil << "grestore\n";
  955.  
  956.     outfil << "showpage\n";
  957.     outfil << "%\n";
  958.  
  959.     outfil.close();
  960. //cerr << "outfile closed";
  961. }
  962.  
  963.  
  964.  
  965. //
  966.  
  967. OffsetDish::OffsetDish() : Antenna()
  968. {               // constructor 
  969.     freq = 0.0;                 
  970.     small_diameter = 0.0;             
  971.     large_diameter = 0.0;             
  972.     odepth = 0.0;
  973.     odepth_position = 0.0;                
  974.     tilt_angle = 0.0;
  975.     focal_length = 0.0;         
  976.     equiv_f_over_D = 0.0;
  977.     f_over_D = 0.0;             
  978.     small_feedangle = 0.0;            
  979.     small_feedang_deg = 0.0;          
  980.     large_feedangle = 0.0;            
  981.     large_feedang_deg = 0.0;          
  982.     R_edge = 0.0;                    
  983.     R_aim = 0.0;
  984.     space_attn = 0.0;           
  985.     desired_taper = 0.0;        
  986.     BW3 = 0.0;                  
  987.     simple_horn_diameter = 0.0; 
  988.     wavelength = 0.0;           
  989.     dish_gain = 0.0;                 
  990.     
  991. }
  992.  
  993. void OffsetDish::offset_init()
  994. {
  995.     cout << "\nPLEASE ENTER:\n\nDiameter of large axis of dish in" << units << ": " ;
  996.     cout.flush();
  997.     cin >> large_diameter ;
  998.     large_diameter *= metric;   //mm
  999.  
  1000.      cout << "\nDiameter of small axis of dish in" << units << ": " ;
  1001.     cout.flush();
  1002.     cin >> small_diameter ;
  1003.     small_diameter *= metric;   //mm
  1004.  
  1005.     cout << "\nDepth of dish at deepest point in" << units << ": " ;
  1006.     cout.flush();
  1007.     cin >> odepth;
  1008.     odepth *= metric;   //mm
  1009.  
  1010.     cout << "\nDistance of deepest point from bottom edge along large axis  in" << units << ": " ;
  1011.     cout.flush();
  1012.     cin >> odepth_position ;
  1013.      odepth_position *= metric;   //mm
  1014.  
  1015. // new equations here
  1016.  
  1017.     tilt_angle = asin(small_diameter / large_diameter);
  1018.     
  1019. // rotate coordinates by tilt angle    
  1020. // bottom
  1021. //    double xb = 0.0;
  1022. //    double yb = 0.0;
  1023. // deepest point
  1024.     double xd = odepth_position * cos(tilt_angle) - odepth * sin(tilt_angle);
  1025.     double yd = odepth_position * sin(tilt_angle) + odepth * cos(tilt_angle);
  1026. //debug// cout << setprecision(5) << "\n          rotated deep point = " << xd << " , " << yd ;
  1027.  
  1028. // top
  1029.     double xt = large_diameter * cos(tilt_angle);
  1030.     double yt = small_diameter; // = large_diameter * sin(tilt_angle);
  1031. //debug// cout << "\n          rotated top point = " << xt << " , " << yt ;
  1032.  
  1033. // curve fitting
  1034.  
  1035. // determinants
  1036.      double Den = 8.0 * xd * yt - 8.0 * xt * yd;
  1037.     double D1 = yd * yd * 2.0 * yt - yt * yt * 2.0 * yd;
  1038.     double D2 = yt * yt * 4.0 * xd - yd * yd * 4.0 * xt;
  1039. //debug// cout << "\n          D = " << Den;    
  1040. //debug// cout << "\n          D1 = " << D1;    
  1041. //debug// cout << "\n          D2 = " << D2;    
  1042.  
  1043.      focal_length = D1 / Den;
  1044.  
  1045. // bottom offset from vertex
  1046.      double yb = - D2 / Den;
  1047.      double xb = yb * yb / (4.0 * focal_length);
  1048.  
  1049. //    focal_length = (diameter * diameter) / ( 16.0 * depth);
  1050.     f_over_D = focal_length / (2.0 * ( yt + yb)) ;
  1051.  
  1052. //    cout << "\n\n     f/D = " << setprecision(2) << f_over_D << "\n" ;
  1053.  
  1054.      cout << "\nFocal length = "
  1055.             << setprecision(4) <<  (focal_length / metric)
  1056.             << " " << units << endl;
  1057.  
  1058.      cout << "\nThis offset reflector is a section of a full parabola with a diameter \nof "
  1059.             << setprecision(5) << (2.0 * ( yt + yb) / metric) << " " << units
  1060.             << "whose vertex is " << setprecision(4) << (xb / metric) << " " << units
  1061.             << "behind and "
  1062.             << (yb / metric) << " " << units << "below"
  1063.             << "\nthe bottom edge of the offset reflector."
  1064.                         << setprecision(2)
  1065.             << "\nThe full parabola has an f/D = " << f_over_D << ", which determines "
  1066.             << "criticality of focal \nlength.";
  1067.  
  1068. // string length
  1069.  
  1070.      double bottom_angle = atan2(yb,(focal_length - xb));
  1071.      double bottom_string = (focal_length - xb) / cos(bottom_angle);
  1072.  
  1073.      double top_angle = atan2(yt,(focal_length - xt));
  1074.      double top_string = yt / sin(top_angle);
  1075.  
  1076.      double aim_angle = bottom_angle + 0.5 * (top_angle - bottom_angle);
  1077.      R_aim = 2.0 * focal_length / (1.0 + cos(aim_angle));
  1078.  
  1079. //debug// cout << "\nbottom angle = " << setprecision(4) << (bottom_angle );
  1080. //debug// cout << "top angle = " << (top_angle );
  1081. //debug// cout << "aim angle = " << (aim_angle );
  1082. //debug// cout << "aiming distance = " << R_aim << units;
  1083.  
  1084.      large_feedangle = top_angle - bottom_angle;
  1085.  
  1086. // this is a reasonable approximation
  1087.      small_feedangle = 2.0 * atan2((small_diameter / 2.0),(R_aim - odepth));
  1088.  
  1089.      cout << "\n\nThe focal point of the dish is "
  1090.             << setprecision(5) << (bottom_string / metric) << " " << units
  1091.             << "from the bottom edge of the \nreflector and "
  1092.             << setprecision(5) << (top_string / metric) << " " << units
  1093.             << "from the top edge of the reflector.\n";
  1094.  
  1095.      cout << " \nFor operation with the main beam on the horizon with the feed at the bottom, "
  1096.             << "\nthe dish must be tilted forward"
  1097.             << " so that the large axis is "
  1098.             << setprecision(3) << (tilt_angle * crad) << " degrees"
  1099.             << " \nabove horizontal." ;
  1100.  
  1101. }
  1102.  
  1103. void OffsetDish::offset_illumination()
  1104. {
  1105. //    feedangle = 2 * atan2(1.0,((2.0 * f_over_D) - (1.0/(8.0 * f_over_D))));
  1106.  
  1107.     large_feedang_deg = crad * large_feedangle ;   // degrees conversion
  1108.     small_feedang_deg = crad * small_feedangle ;   // degrees conversion
  1109.  
  1110.     cout << "\n\nIllumination angle for feed = "
  1111.           << setprecision(3) <<  large_feedang_deg
  1112.                         << " degrees on the large axis\n"
  1113.           << "and "<< setprecision(3) <<  small_feedang_deg
  1114.                         << " degrees on the small axis.";
  1115.  
  1116.  
  1117.         // R_edge = distance from focal point to edge
  1118.  
  1119. // some reasonable approximations for feeds
  1120.     equiv_f_over_D = R_aim / small_diameter;
  1121.  
  1122.     R_edge = 2.0 * R_aim/ ( 1 + cos(small_feedangle/2.0));
  1123.  
  1124.         // Space_attn is additional path loss to edge of dish
  1125.     double Space_attn = (20.0 * log10(R_edge / R_aim));
  1126.  
  1127.         // Desired_taper to achieve 10 dB actual edge taper
  1128.     double Desired_taper = 10.0 - Space_attn;  // dB
  1129.  
  1130.     BW3 = small_feedangle * sqrt( 3.0 / Desired_taper) ;
  1131.  
  1132.     cout << "\nA feedhorn with a 3 dB beamwidth of "
  1133.           << setprecision(3) << (BW3 * crad) << " degrees is needed,"
  1134.           << "\nequivalent to the feed for a conventional dish with f/D = "
  1135.           << setprecision(2) << equiv_f_over_D ;
  1136.  
  1137. //    double Simple_horn_diameter = 66.0 / (BW3 * crad) ; // wavelengths
  1138.  
  1139.  
  1140. //debug//    cout << "\n  Space attenuation = "
  1141. //debug//          << setprecision(2) << Space_attn << " dB ";
  1142. //debug//    cout << "\n  Desired taper = "
  1143. //debug//          << setprecision(2) << Desired_taper << " db "
  1144. //debug//          << "for 10 dB edge illumination";
  1145.  
  1146. //    cout << "\n\nA simple feed horn would have a diameter of "
  1147. //         << setprecision(2) << Simple_horn_diameter << " wavelengths";
  1148.  
  1149.         fod = equiv_f_over_D;
  1150.  
  1151. // straight line approximation to G3RPE curves - within 2% for f/D < 0.8
  1152. // for small axis only
  1153.  
  1154.     H_aperture = wavelength * ((equiv_f_over_D * 2.864) - 0.575);
  1155.         
  1156.     E_aperture = wavelength * ((equiv_f_over_D * 1.727) - 0.129);
  1157.  
  1158.      axial_length = H_aperture; //any rough guess - correct for phase centers later
  1159.  
  1160. }
  1161.  
  1162. void OffsetDish::offset_calc_gain()
  1163. {
  1164.     efficiency = 0.5;     // assume 50% efficiency
  1165.  
  1166.     double radius = 0.5 * small_diameter;
  1167.  
  1168.     aperture = pi * radius * radius;
  1169.  
  1170.     dish_gain = efficiency * aperture * 4.0 * pi / (wavelength * wavelength);
  1171.  
  1172.     dish_gain = 10.0 * log10(dish_gain);
  1173.  
  1174.     cout << "\n\nGain at 50% efficiency = " << setprecision(3) << dish_gain
  1175.      << " dBi ";
  1176.  
  1177.     efficiency = 0.6;     // recalculate for 60% efficiency
  1178.     dish_gain = efficiency * aperture * 4.0 * pi / (wavelength * wavelength);
  1179.     dish_gain = 10.0 * log10(dish_gain);
  1180.  
  1181.     cout << "\nIf you do really well, you might get 60% efficiency for a gain = "
  1182.             << setprecision(3) << dish_gain << " dBi ";
  1183.     cout << "\n\nTo design a feedhorn, use f/D = "
  1184.          << setprecision(2) << equiv_f_over_D 
  1185.          << " in Menu option F";
  1186.  
  1187. }
  1188.  
  1189.  
  1190.  
  1191. //
  1192.  
  1193.  
  1194.  
  1195.  
  1196.  
  1197. Horn::Horn() : Antenna()
  1198. {               // constructor 
  1199.     freq = 0;        
  1200.     H_wg = 0;        
  1201.     E_wg = 0;        
  1202.     wavelength = 0;  
  1203.     horn_gain = 0;        
  1204.     axial_length = 0;
  1205.     H_aperture = 0;
  1206.     E_aperture = 0;   
  1207.     E_phase_center = 0;
  1208.     H_phase_center = 0;
  1209.     simplegain = 0;        
  1210.     E_flare_angle = 0;
  1211.     E_side = 0;
  1212.     E_ang = 0;
  1213.     H_flare_angle = 0;
  1214.     H_side = 0;
  1215.     H_ang = 0;
  1216. }
  1217.             
  1218.  
  1219. void Antenna::get_freq()
  1220. {                   // reads initial data
  1221.     cout << "\n" << "Frequency in MHz: " ;
  1222.     cout.flush();
  1223.     cin >> freq ;
  1224.  
  1225.     wavelength = c / (1000.0 * freq);
  1226. }
  1227.  
  1228. void Antenna::get_wg()
  1229. {
  1230.     cout << "         ____________     \n";
  1231.     cout << "        |     E      |   waveguide  \n";
  1232.     cout << "        |     ^ -->H |             Hint: for WR-90\n";
  1233.     cout << "        |     |      |               H = 22.86 mm. = 0.9 in.,\n";
  1234.     cout << "         ------------                E = 10.16 mm. = 0.4 in. \n\n";
  1235.  
  1236.     bad = 1 ;
  1237.     while (bad >= 1)
  1238.     {    
  1239.         cout << "\n" << "Enter H-plane inside dimension of waveguide in "
  1240.              << units << ": ";
  1241.     cout.flush();
  1242.     cin >> H_wg;
  1243.         H_wg *= metric;         //mm
  1244.  
  1245.         cout << "\n" << "Enter E-plane inside dimension of waveguide in "
  1246.              << units << ": ";
  1247.     cout.flush();
  1248.     cin >> E_wg;
  1249.         E_wg *= metric;         //mm
  1250.     
  1251.     if (wavelength < (0.98 * H_wg) || wavelength > ( 1.72 * H_wg ))
  1252.                         /* slight fudge to get edges */
  1253.         {
  1254.             cout << " ERROR - frequency out of waveguide range \n";
  1255.             bad++ ;
  1256.             if (bad > 3) break;
  1257.         }
  1258.         else bad = 0;
  1259.     }
  1260. }
  1261.  
  1262. void Antenna::check_aperture()
  1263. {
  1264.     if ( H_wg > H_aperture)
  1265.     {
  1266.         cout << "\n\n *** ERROR - waveguide H dimension larger than horn"
  1267.              << " aperture \n\n"
  1268.              << " *** Probably can't use a rectangular feedhorn for this"
  1269.              << " f/D and waveguide.\n";
  1270.         bad = 4;   
  1271.     }        
  1272. }     
  1273.  
  1274.  
  1275. void Antenna::horn_dimensions()
  1276. {                               // input dimensions of a horn
  1277.         
  1278.     cout << "\n" << "ENTER DESIRED PHYSICAL DIMENSIONS OF HORN: ";
  1279.     
  1280.  
  1281.     cout << "\n" << "Enter axial length of horn in "
  1282.          << units << ": ";
  1283.     cout.flush();
  1284.     cin >> axial_length;
  1285.     axial_length *= metric;
  1286.     
  1287.     cout << "\n" << "Enter H-plane aperture of horn in "
  1288.          << units << ": ";
  1289.     cout.flush();
  1290.     cin >> H_aperture;
  1291.     H_aperture *= metric;
  1292.     
  1293.     cout << "\n" << "Enter E-plane aperture of horn in "
  1294.          << units << ": ";
  1295.     cout.flush();
  1296.     cin >> E_aperture;
  1297.     E_aperture *= metric;
  1298. }        
  1299.  
  1300. void Antenna::G3RPE_approximation(double target_f_over_D)
  1301. {
  1302. // straight line approximation to G3RPE curves for rectangular feedhorn 
  1303. // - within 2% for f/D < 0.8
  1304.  
  1305.  
  1306.     H_aperture = wavelength * ((target_f_over_D * 2.864) - 0.575);
  1307.         
  1308.     E_aperture = wavelength * ((target_f_over_D * 1.727) - 0.129);
  1309.  
  1310.     double apex_length = H_aperture * H_aperture / wavelength; //approximation
  1311.  
  1312.     axial_length = apex_length * ( (H_aperture - H_wg) / H_aperture);
  1313.  
  1314.     cout << "\n\nEstimated feedhorn dimensions:";
  1315.     cout << "\n\n   H aperture = " << (H_aperture/metric) << " " << units
  1316.          << "\n   E aperture = " << (E_aperture/metric) << " " << units
  1317.          << "\n   Axial length = " << (axial_length/metric) << " " << units
  1318.          << endl;
  1319.     cout << "\n\n *** YOU must adjust the length of the horn to "
  1320.             << "match phase centers ***\n";
  1321. }
  1322.  
  1323. void Horn::lookup()
  1324. {
  1325.  
  1326. //   Lookup table based on 
  1327. //    D.E. Cozzens, "Tables Ease Horn Design," _Microwaves_, March 1966, p37.
  1328. //   from which I eyeballed nominal values;
  1329. //   anyway, the program calculates a new gain later 
  1330.          
  1331.     float G[ 26];
  1332.     
  1333.     for (int i = 0; i < 10; i++)
  1334.         G[i] = 0;
  1335.         
  1336.     G[10] = 0.080;
  1337.     G[11] = 0.24;
  1338.     G[12] = 0.4;
  1339.     G[13] = 0.6;
  1340.     G[14] = 0.88;
  1341.     G[15] = 1.25;
  1342.     G[16] = 1.7;
  1343.     G[17] = 2.25;
  1344.     G[18] = 3.0;
  1345.     G[19] = 4.0;
  1346.     G[20] = 5.2;
  1347.     G[21] = 6.7;
  1348.     G[22] = 8.7;
  1349.     G[23] = 11.2;
  1350.     G[24] = 14.3;
  1351.     G[25] = 18.3;
  1352.  
  1353.     bad = 1;
  1354.     
  1355.     double gain;    
  1356.  
  1357.     while (bad)
  1358.     {
  1359.         cout << "\n" << "Enter desired gain of horn in dB: ";
  1360.     cout.flush();
  1361.     cin >> gain;
  1362.  
  1363.         if ((gain < 10.0) || (gain > 25.0))
  1364.             cout << "Gain must be between 10 and 25 dB";
  1365.         else bad = 0;
  1366.     }        
  1367.  
  1368.     axial_length = wavelength * G[int(gain)];
  1369.  
  1370. // {need gain as a ratio to find horn apertures }
  1371. // {**** NOTE y=z**x -> y:=exp(x*ln(z)) ****}
  1372.  
  1373.     double gain_ratio = exp(0.2302585 * (int(gain)));            
  1374.  
  1375.     H_aperture = wavelength * 0.4675 * sqrt(gain_ratio);
  1376.  
  1377.     E_aperture = wavelength * 0.3463 * sqrt(gain_ratio);
  1378.  
  1379.     cout << "\n" << " CALCULATED HORN DIMENSIONS: \n";   
  1380.     
  1381.     cout << "\n" << "   Axial length of horn is "
  1382.          << setprecision(4) << (axial_length/metric) << " "
  1383.      << units;
  1384.     cout << "\n" << "   H-plane aperture of horn is "
  1385.      << setprecision(4) << (H_aperture/metric) << " "
  1386.      << units;
  1387.     cout << "\n" << "   E-plane aperture of horn is "
  1388.      << setprecision(4) << (E_aperture/metric) << " "
  1389.      << units;
  1390. }
  1391.  
  1392.  
  1393. void Horn::simple_gain()
  1394. {                 // temp - simple formula from Kraus
  1395.  
  1396.     simplegain = 4.5 * (H_aperture/wavelength) * (E_aperture/wavelength);
  1397.  
  1398.     simplegain = 10.0 * log10(simplegain) + 2.14 ;   //{ dBi }
  1399.             
  1400. //    cout << " Simple gain of horn is "
  1401. //         << setprecision(3) << simplegain << " dBi \n";
  1402. }            
  1403.  
  1404. double Le(double s)
  1405. {
  1406. //    MathCad fit by Matt Reilly of Fig. 23 from Balanis
  1407.  
  1408. //    input is Maximum input phase error in wavelengths
  1409. //    returns loss due to phase error in dB.
  1410.  
  1411. //    Le(s) = sum(from i=1 to 10) Xle[i] * s^i
  1412.  
  1413.     if ( s < 0 || s > 1)
  1414.     {
  1415.         cerr << "ERROR: excessive phase error in Le\n\n";
  1416.         return 1;
  1417.     }
  1418.  
  1419.     double Xle[11];
  1420.  
  1421. // Xle[i] = 
  1422.     Xle[1] =   10.5075396618;
  1423.     Xle[2] =  -236.610713851;
  1424.     Xle[3] =   2603.14290758;
  1425.     Xle[4] =  -15318.8133545;
  1426.     Xle[5] =   55318.7209697;
  1427.     Xle[6] =  -125471.932662;
  1428.     Xle[7] =   178426.752358;
  1429.     Xle[8] =  -153811.177005;
  1430.     Xle[9] =   73233.5757222;
  1431.     Xle[10] =  -14743.1657614;
  1432.  
  1433.     double Le = 0;
  1434.  
  1435.     for (int i = 1; i < 11; i++)
  1436.     {
  1437.     Le += Xle[i] * pow(s,i);
  1438.     }
  1439.     return Le;
  1440. }
  1441.  
  1442. double Lh(double t)
  1443. {
  1444. //    MathCad fit by Matt Reilly of Fig. 23 from Balanis
  1445.  
  1446. //    input is Maximum input phase error in wavelengths
  1447. //    returns loss due to phase error in dB.
  1448.  
  1449. //    Lh(t) = sum(from i=1 to 10) Xlh[i] * t^i
  1450.  
  1451.     if ( t < 0 || t > 1)
  1452.     {
  1453.         cerr << "ERROR: excessive phase error in Lh\n\n";
  1454.         return 1;
  1455.     }
  1456.  
  1457.     double Xlh[11];
  1458.  
  1459. // Xlh[i] =
  1460.     Xlh[1] =   -13.9134920465;
  1461.     Xlh[2] =      398.4347217;
  1462.     Xlh[3] =   -4241.37951372;
  1463.     Xlh[4] =    24010.7335428;
  1464.     Xlh[5] =    -79636.863311;
  1465.     Xlh[6] =    162957.754379;
  1466.     Xlh[7] =   -208325.065791;
  1467.     Xlh[8] =    162037.036743;
  1468.     Xlh[9] =   -70133.3772858;
  1469.     Xlh[10] =     12951.940007;
  1470.  
  1471.     double Lh = 0;
  1472.  
  1473.     for (int i = 1; i < 11; i++)
  1474.     {
  1475.         Lh += Xlh[i] * pow(t,i);
  1476.     }
  1477.     return Lh;
  1478. }
  1479.  
  1480. double phase_error(double aperture, double flare_angle, double wavelength)
  1481. {
  1482.     double rho = 0.5 * aperture / sin(flare_angle);
  1483. //cout << setprecision(4) << "\n aperture = " << aperture
  1484. //     << " flare angle = " << flare_angle
  1485. //     << " rho =  " << rho ;   
  1486.     double error = aperture * aperture / ( 8.0 * wavelength * rho );
  1487.     
  1488.     return error;
  1489. }
  1490.  
  1491. void Antenna::horn_calcgain()
  1492. {
  1493. //improved algorithm from
  1494. // Balanis, C.A., "Horn Antennas", Chapter 8 in 
  1495. // Lo, Y.T. and Lee, S.W.
  1496. // Antenna Handbook: Theory, Applications and Design, Van Nostrand, 1988
  1497. // pp 8-39 to 8-42.
  1498.  
  1499.  
  1500.     horn_gain = 10.0 * ( 1.008 + 
  1501.                  log10( E_aperture * H_aperture / (wavelength * wavelength)));
  1502.  
  1503.  
  1504. // correct for phase error
  1505.  
  1506.  
  1507.     double s = phase_error(E_aperture, H_flare_angle, wavelength);
  1508. //cout << setprecision(4) << "\n s = " << s << "  Le(s) = " << (Le(s));
  1509.  
  1510.     double t = phase_error(H_aperture, E_flare_angle, wavelength);
  1511. //cout << setprecision(4) << "\n t = " << t << "  Lh(t) = " << (Lh(t)) << endl;
  1512.  
  1513.     horn_gain -= (Le(s) + Lh(t));               // dBi
  1514.  
  1515. //    cout << " Improved gain of horn is "
  1516. //         << setprecision(3) << horn_gain << " dBi \n";
  1517.  
  1518. }
  1519.  
  1520.  
  1521. void Horn::write_data(ostream& ostrm, int interactive)
  1522. {
  1523.     // anti warning hack.
  1524.     int i, j;
  1525.     for(i = j = 0; i < 10; i++) j = j + interactive;
  1526.  
  1527.     ostrm << " \nSimple gain of horn is "
  1528.       << setprecision(3) << simplegain << " dBi \n";
  1529.  
  1530.     ostrm << "                Improved gain of horn is "
  1531.       << setprecision(3) << horn_gain << " dBi \n\n";
  1532.  
  1533.     ostrm << "H-Plane phase center is "
  1534.          << setprecision(3) << H_phase_center
  1535.          << " wavelengths inside horn mouth\n"; 
  1536.     ostrm << "E-Plane phase center is "
  1537.       << setprecision(3) << E_phase_center
  1538.       << " wavelengths inside horn mouth\n";
  1539. }
  1540.  
  1541. void Antenna::horn_angles()
  1542. {                
  1543. // note definition of E_flare_angle is the angle that the E side is 
  1544. // flared at, which is the flare angle in the H plane
  1545.  
  1546.     E_flare_angle = atan2((0.5 * (H_aperture - H_wg)) , axial_length);
  1547.     E_side = axial_length / cos(E_flare_angle);
  1548.     E_ang = atan2((0.5 * (E_aperture - E_wg)) , E_side);
  1549.  
  1550.     H_flare_angle = atan2((0.5 * (E_aperture - E_wg)) , axial_length);
  1551.     H_side = axial_length / cos(H_flare_angle);
  1552.     H_ang = atan2((0.5 * (H_aperture - H_wg)) , H_side);
  1553.  
  1554. // test
  1555.  
  1556. //    cout << setprecision(4) 
  1557. //         << "Flare angles " << E_flare_angle << "   " << H_flare_angle << "\n";
  1558. //    cout << setprecision(4) 
  1559. //         <<  "Side lengths" << E_side << "   " << H_side << "\n";
  1560. //    cout << setprecision(4) 
  1561. //         << "Angles " << E_ang << "   " << H_ang << "\n";
  1562. }
  1563.  
  1564.  
  1565. void Horn::coords()
  1566. {
  1567. // TEST
  1568. //    cout << " ENTERING fixed Horn::coords()" << endl;
  1569.  
  1570.     double fold_ang = E_ang + H_ang;
  1571.  
  1572.     inner[1] = inner[0] + Point(E_wg,0);
  1573.  
  1574.     inner[2] = inner[1] + Point((H_wg * cos(fold_ang)),-(H_wg * sin(fold_ang)));
  1575.  
  1576.     inner[3] = inner[2] + Point((E_wg * cos(2 * fold_ang)),
  1577.                                 -(E_wg * sin(2 * fold_ang)));
  1578.                            
  1579.     inner[4] = inner[3] + Point((H_wg * cos(3 * fold_ang)),
  1580.                                 -(H_wg * sin(3 * fold_ang)));
  1581.  
  1582.     outer[0] += Point(-(0.5 * (E_aperture - E_wg)),E_side);
  1583.  
  1584.     outer[1] = outer[0] + Point(E_aperture,0);
  1585.  
  1586.     outer[2] = outer[1] + Point((H_aperture * cos(fold_ang)),
  1587.                 -(H_aperture * sin(fold_ang)));
  1588.  
  1589.     outer[3] = outer[2] + Point((E_aperture * cos(2 * fold_ang)),
  1590.                 -(E_aperture * sin(2 * fold_ang)));
  1591.  
  1592.     outer[4] = outer[3] + Point((H_aperture * cos(3 * fold_ang)),
  1593.                 -(H_aperture * sin(3 * fold_ang)));
  1594.  
  1595.     // and a solder flap
  1596.  
  1597.  
  1598.     inner[5] = inner[4] + Point((7 * cos(3*fold_ang - 0.7854 + H_ang)),
  1599.                    (-(7 * sin(3*fold_ang - 0.7854 + H_ang))));
  1600.  
  1601.     outer[5] = outer[4] + Point((7 * cos(3*fold_ang + 0.7854 + H_ang)),
  1602.                                 (-(7 * sin(3*fold_ang + 0.7854 + H_ang))));
  1603.  
  1604.  
  1605.  
  1606. //%t   cout << "H_angle = " << H_ang << endl;
  1607.     
  1608. //%t   cout << "fold_angle = " << fold_ang << endl;
  1609.     
  1610. //%t   Point in5_pt = Point((7 * cos(3*fold_ang - 0.7854 + H_ang)),
  1611. //                   (-(7 * cos(3*fold_ang - 0.7854 + H_ang))));
  1612.  
  1613. //%t   cout << "inner_5 increment = " << in5_pt << endl;
  1614.  
  1615. //%t   Point out5_pt = Point((7 * cos(3*fold_ang + 0.7854 + H_ang)),
  1616. //                (-(7 * cos(3*fold_ang + 0.7854 + H_ang))));
  1617.  
  1618. //%t   cout << "outer_5 increment = " << out5_pt << endl;
  1619.  
  1620. }
  1621. //
  1622.  
  1623.  
  1624.  
  1625.  
  1626.  
  1627.  
  1628. void Horn::PS_template()
  1629. {                      // PostScript template on one page
  1630.                        // or two pages for larger horns
  1631.                        
  1632.     char descriptor[LINESIZE] = " ";
  1633.     char outname[LINESIZE];
  1634.  
  1635.     cin.ignore(LINESIZE,'\n');
  1636.     cout << " Horn description line: ";
  1637.     cout.flush();
  1638.     cin.get(descriptor,LINESIZE,'\n');
  1639.  
  1640.     cout << "File name for horn template (should be .PS ): ";
  1641.     cout.flush();
  1642.     cin >> outname ;
  1643.  
  1644.     ofstream outfil(outname);
  1645.  
  1646.     if (!outfil) 
  1647.     {
  1648.         cerr << "Cannot open output file for output";
  1649.     }
  1650.     
  1651.     int pages = 2;
  1652.     
  1653.     Point offset;
  1654.  
  1655.     if ((outer[0].y() - outer[4].y()) < 260)         // horn fits on page 
  1656.     {
  1657.         pages = 1;
  1658.         if (outer[4].x() < outer[0].x())
  1659.             offset = Point(-outer[4].x(), -outer[0].y());
  1660.         else offset = Point(-outer[0].x(), -outer[0].y());
  1661.     }
  1662.     else offset = Point(-outer[0].x(), -outer[0].y());
  1663.  
  1664.     offset =  Point(25,254) + offset;
  1665.             
  1666.     
  1667. //      PostScript header 
  1668.  
  1669.     outfil << "%! PostScript \n";
  1670.     outfil << "/mm { 2.834646 mul } def\n";
  1671.     outfil << "/in { 72 mul } def\n";
  1672.  
  1673.     outfil << "%\n";
  1674.     outfil << "% 100% scaling factors - change for printer correction\n";
  1675.     outfil << "1.0 1.0 scale \n";
  1676.     outfil << "%\n";
  1677.  
  1678.     outfil << setprecision(3)
  1679.            << "% Template for " << horn_gain << " dBi pyramidal horn for" 
  1680.            << setprecision(5)
  1681.            << freq << " MHz" << endl;
  1682.     outfil << "% generated by HDLANT21 by N1BWT 1994,1995,1996 " << endl;
  1683.     outfil << "%" << endl;
  1684.     outfil << "%" << descriptor;
  1685.     outfil << "%" << endl;
  1686.     outfil << "% Print on PostScript printer" << endl;
  1687.     outfil << "% stick to flashing copper";
  1688.     outfil << "% and cut out pieces." << endl;
  1689.     outfil << "% Then fold up and solder horn";
  1690.     outfil << "% then solder it to waveguide flange." << endl;
  1691.     outfil << setprecision(4);
  1692.     outfil << "% Waveguide size is " << (H_wg/metric) << " "
  1693.            << units << " x " << (E_wg/metric) << " " << units << "\n";
  1694.     outfil << "%" << endl;
  1695.     outfil << "%" << endl;
  1696.     
  1697.     outfil << "gsave" << endl;
  1698.     outfil << "% HORN **********************************************" << endl;
  1699.     outfil << "%" << endl;
  1700.     
  1701.     outfil << offset.x() << " mm " << offset.y() << " mm translate" << endl;
  1702.     
  1703.     outfil << "%" << endl;
  1704.     outfil << "%" << endl;
  1705.     outfil << "% HORN" << endl;
  1706.     outfil << "%" << endl;
  1707.  
  1708. // Text
  1709.  
  1710.     outfil << "/Helvetica-Bold findfont" << endl;
  1711.     outfil << "14 scalefont" << endl;
  1712.     outfil << "setfont" << endl;
  1713.  
  1714.     outfil << (outer[0].x() + 10) << " mm "
  1715.            << (outer[1].y() + 12) << " mm moveto" << endl;
  1716.  
  1717.     outfil << "(Template for " << horn_gain << " dBi horn for "
  1718.        <<  int(freq) << " MHz) show" << endl;
  1719.  
  1720.     outfil << "-10.0 mm " << (outer[1].y() - 7) << " mm moveto" << endl;
  1721.  
  1722.     outfil << "(E-plane) show" << endl;
  1723.     outfil << "-10.0 mm " << (outer[1].y() - 14) << " mm moveto" << endl;
  1724.  
  1725.     outfil << " (N1BWT 1994) show " << endl;
  1726.  
  1727. // and horn outline for single page
  1728.  
  1729.     if (pages == 1)
  1730.     {
  1731.         outfil << "newpath" << endl;
  1732.         outfil << PS_moveto() << "\n";
  1733.             
  1734.         for (int i = 0; i <= 4; i++)
  1735.             outfil << PS_lineto(outer[i]) << "\n";
  1736.  
  1737.         for ( i = 4; i >= 0; i--)
  1738.             outfil << PS_lineto(inner[i]) << "\n";
  1739.  
  1740.         outfil << "stroke" << endl;
  1741.  
  1742.         outfil << "%" << endl;
  1743.  
  1744. // and fold lines 
  1745.  
  1746.         outfil << "% fold lines" << endl;
  1747.  
  1748.  
  1749.         for ( i = 0; i <= 5; i++)
  1750.         {
  1751.             outfil << "newpath" << endl;
  1752.             outfil << "[10 10] 0 setdash\n" ;
  1753.             outfil << PS_moveto(inner[i]) << "\n";
  1754.             outfil << PS_lineto(outer[i]) << "\n";
  1755.             outfil << "stroke" << endl;
  1756.         }
  1757.  
  1758.         outfil << "% finish solder flap" << endl;
  1759.  
  1760.         outfil << "newpath" << endl;
  1761.         outfil << "[10 10] 0 setdash\n" ;
  1762.         outfil << PS_moveto(inner[4]) << "\n";
  1763.         outfil << PS_lineto(inner[5]) << "\n";
  1764.         outfil << "stroke" << endl;
  1765.  
  1766.         outfil << "newpath" << endl;
  1767.         outfil << "[10 10] 0 setdash\n" ;
  1768.         outfil << PS_moveto(outer[4]) << "\n";
  1769.         outfil << PS_lineto(outer[5]) << "\n";
  1770.         outfil << "stroke" << endl;
  1771.  
  1772.         outfil << "% END HORN ***************************************" << endl;
  1773.         outfil << "grestore" << endl;
  1774.  
  1775.         outfil << "showpage" << endl;
  1776.  
  1777.     }
  1778.     
  1779.     else        // two pages
  1780.     {
  1781.  
  1782. // E-plane side: coordinates same as single page
  1783.  
  1784. outfil << "% E-plane side of HORN ***************************************\n";
  1785.  
  1786.  
  1787.         outfil << "newpath" << endl;
  1788.         outfil << PS_moveto() << "\n";
  1789.             
  1790.         for (int i = 0; i <= 1; i++)
  1791.             outfil << PS_lineto(outer[i]) << "\n";
  1792.  
  1793.         for ( i = 1; i >= 0; i--)
  1794.             outfil << PS_lineto(inner[i]) << "\n";
  1795.  
  1796.         outfil << "stroke" << endl;
  1797.  
  1798.         outfil << "%" << endl;
  1799.     
  1800.         outfil << "% END E-plane side of HORN ****************************\n";
  1801.         outfil << "grestore\n";
  1802.  
  1803.         outfil << "showpage\n";
  1804.         outfil << "%\n";
  1805.  
  1806. // H-plane side: new coordinates
  1807.  
  1808.         outfil << "gsave" << endl;
  1809. outfil << "% H-plane side of HORN ***************************************\n";
  1810.  
  1811. // center large aperture as well as we can
  1812.  
  1813.  
  1814.         if (H_aperture > 190)
  1815.             offset = Point((0.5 * (215.0 - H_aperture) - outer[0].x()),
  1816.                             (254 - outer[0].y()));
  1817.                             
  1818.         outfil << "%" << endl;
  1819.     
  1820.     outfil << offset.x() << " mm " << offset.y() << " mm translate" << endl;
  1821.     
  1822.         outfil << "%" << endl;
  1823.  
  1824.         inner[1] = inner[0] + Point(H_wg,0);
  1825.  
  1826.         outer[0] = Point(-(0.5 * (H_aperture - H_wg)),H_side);
  1827.  
  1828.         outer[1] = outer[0] + Point(H_aperture,0);
  1829.  
  1830.         outfil << "newpath" << endl;
  1831.         outfil << PS_moveto() << "\n";
  1832.             
  1833.         for ( i = 0; i <= 1; i++)
  1834.             outfil << PS_lineto(outer[i]) << "\n";
  1835.  
  1836.         for ( i = 1; i >= 0; i--)
  1837.             outfil << PS_lineto(inner[i]) << "\n";
  1838.  
  1839.         outfil << "stroke" << endl;
  1840.  
  1841.         outfil << "%" << endl;
  1842.  
  1843.         outfil << "% END E-plane side of HORN ****************************\n";
  1844.  
  1845.  
  1846. // text for H-plane side
  1847.  
  1848.         outfil << "/Helvetica-Bold findfont" << endl;
  1849.         outfil << "14 scalefont" << endl;
  1850.         outfil << "setfont" << endl;
  1851.     
  1852.         outfil << (outer[0].x() + 10) << " mm "
  1853.                << (outer[1].y() + 12) << " mm moveto" << endl;
  1854.     
  1855.         outfil << "(Template for " << horn_gain << " dBi horn for "
  1856.                <<  int(freq) << " MHz) show" << endl;
  1857.     
  1858.         outfil << "-10.0 mm " << (outer[1].y() - 7) << " mm moveto" << endl;
  1859.     
  1860.         outfil << "(H-plane) show" << endl;
  1861.         outfil << "-10.0 mm " << (outer[1].y() - 14) << " mm moveto" << endl;
  1862.     
  1863.         outfil << " (N1BWT 1994) show " << endl;
  1864.  
  1865.         outfil << "grestore\n";
  1866.         outfil << "showpage\n";
  1867.         outfil << "%\n";
  1868.         
  1869.         outfil.close();
  1870.     }
  1871. }    
  1872.  
  1873.  
  1874. //
  1875.  
  1876.  
  1877.  
  1878.  
  1879.  
  1880.  
  1881. //* predeclare entry points for phase center routines */
  1882.     double Phase_center(char, float, float, float, float);
  1883.     double H_Phase_Center(double, double, double, double&, double&);
  1884.     double E_Phase_Center(double, double, double, double&, double&);
  1885.     double fresnel_sin(double, double&, double&);
  1886.     double fresnel_cos(double, double&, double&);
  1887.  
  1888.  
  1889. void Antenna::horn_phasecenters()
  1890. {
  1891.  
  1892. /* get the phase centers and decide what to do about them */
  1893.  
  1894.     E_phase_center = Phase_center('E', E_aperture, E_wg, 
  1895.                                     wavelength, axial_length);
  1896.     H_phase_center = Phase_center('H', H_aperture, H_wg, 
  1897.                                     wavelength, axial_length);
  1898.  
  1899. //    cout << "E-Plane phase center is "
  1900. //     << setprecision(2) << E_phase_center
  1901. //     << " wavelengths inside horn mouth\n";
  1902. //    cout << "H-Plane phase center is "
  1903. //         << setprecision(2) << H_phase_center
  1904. //         << " wavelengths inside horn mouth\n\n"; 
  1905.  
  1906. }
  1907.  
  1908. double Pi, Pi2, Pi2sq;     // /* precomputed values for Pi and Pi/2
  1909.  
  1910. #define    ERRMARGIN    2.0E-3
  1911. #define    MAX(a,b)    (a > b ? a : b)
  1912. #define    MIN(a,b)    (a < b ? a : b)
  1913.  
  1914.  
  1915. double Phase_center(char plane, float aperture, float guide, 
  1916.                     float wavelength, float Horn_length)
  1917. //    /* convert to wavelengths for phase center routine */
  1918. //    char plane ;        /* E or H plane */
  1919. //    double aperture ;   /* aperture dimension in mm */
  1920. //    double guide ;      /* waveguide dimension in mm */
  1921.     
  1922. {
  1923.     double side_length ;    /* length of horn side in wavelengths */
  1924.     double Ap_lambda ;      /* aperture in wavelengths */
  1925.     double v ;              /* sqrt(side_length/2.0) */
  1926.     double dmin, dmax ;     /* limits check on phase center */
  1927.     double PC ;             /* phase center in wavelengths */
  1928.  
  1929.     Ap_lambda = aperture / wavelength ;
  1930.     side_length = sqrt(Horn_length*Horn_length +
  1931.              ((aperture - guide)/2.0)*((aperture - guide)/2.0));
  1932.     side_length = side_length / wavelength ;
  1933.     v = sqrt(side_length/2.0);
  1934.  
  1935.  
  1936.     if (plane == 'E')
  1937.         PC = E_Phase_Center( Ap_lambda, v, side_length, dmin, dmax);
  1938.     else 
  1939.         PC = H_Phase_Center( Ap_lambda, v, side_length, dmin, dmax);
  1940.  
  1941. /* test for bad phase center */
  1942.  
  1943.     if ( fabs(dmax - dmin) != (fabs(dmax) - fabs(dmin)))
  1944.         cerr << " \n\nERROR: BUG in "
  1945.              << plane << "_Phase_Center function\n\n";// call Matt\n";
  1946.     else if ((fabs(dmax - dmin) > (PC /16.0)) && (Ap_lambda > 1.0))
  1947.         cerr << " \n\nEXCESSIVE ERROR in "
  1948.              << plane << "_Phase_Center function \n\n";
  1949.         
  1950.     return (PC);
  1951. }
  1952. //
  1953.  
  1954.  
  1955.  
  1956.  
  1957.  
  1958.  
  1959.  
  1960.  
  1961.  
  1962.  
  1963.  
  1964.  
  1965.     
  1966.  
  1967. /* 
  1968.  
  1969.  */
  1970.  
  1971.     
  1972. ///* phase_center.c     Matt Reilly 10/28/91 */
  1973. // converted for C++  2/17/94 pcw
  1974. ///* input data:  a       aperture in wavelengths
  1975. //                l       length of horn side in wavelengths
  1976. //                v       sqrt(l/2) in wavelengths
  1977. //                lv      low de value  - error check
  1978. //                hv      high de value -  "     "
  1979. //                
  1980. //    E_Phase_Center returns distance in wavelengths from mouth of horn to
  1981. //        E-plane phase center inside horn.
  1982. //
  1983. //    H_Phase_Center returns distance in wavelengths from mouth of horn to
  1984. //        H-plane phase center inside horn.
  1985. //
  1986. //*/
  1987.  
  1988. void phase_init()
  1989. {
  1990.     ph_init = 0;
  1991. }
  1992.  
  1993. double epc(double l, double q, double c2, double s2, double C, double S)
  1994. //double l, q, c2, s2, C, S;
  1995. {
  1996.     return l * ( 1 - q * (c2 * C + s2 * S) / (C * C + S * S));
  1997. }
  1998.  
  1999. double E_Phase_Center(double a, double v, double l, double &lv, double &hv)
  2000. //double a, v, l;
  2001. //double * lv, * hv;
  2002. {
  2003.     double q, c2, s2, fc, fcl, fch, fs, fsl, fsh, res;
  2004.     
  2005.     if(ph_init) phase_init();
  2006.     
  2007.     q = a / (2 * v);
  2008.     
  2009.     fc = fresnel_cos(q, fcl, fch);
  2010.     fs = fresnel_sin(q, fsl, fsh);
  2011.     
  2012.     c2 = cos(Pi2 * q * q);
  2013.     s2 = sin(Pi2 * q * q);
  2014.     
  2015.     res = epc(l, q, c2, s2, fc, fs);
  2016.     hv = epc(l, q, c2, s2, fch, fsh);
  2017.     lv = epc(l, q, c2, s2, fcl, fsl);
  2018.     
  2019.     return res;
  2020. }
  2021.  
  2022.  
  2023. double hpc(double l, double r, double t, double c, double s)
  2024. //double l, r, t, c, s;
  2025. {
  2026.     return l * (1 + (((r * c) + (t * s)) / ((c * c) + (s * s))));
  2027. }
  2028.  
  2029. double H_Phase_Center(double a, double v, double l, double &lv, double &hv)
  2030. //double a, v, l;
  2031. //double * lv, * hv;
  2032. {
  2033.     double U, W, CD, CDH, CDL, SD, SDH, SDL, R, T, u2, w2;
  2034.     double su, sul, suh, sw, swl, swh;
  2035.     double cu, cul, cuh, cw, cwl, cwh;
  2036.     double res;
  2037.  
  2038.  
  2039.     if(ph_init) phase_init();
  2040.         
  2041.     U = v / a + a / (2 * v);
  2042.     W = v / a - a / (2 * v);
  2043.     u2 = Pi2 * U * U;
  2044.     w2 = Pi2 * W * W;
  2045.     
  2046.     
  2047.     R = W * cos(u2) - U * cos(w2);
  2048.     T = U * sin(w2) - W * sin(u2);
  2049.     
  2050.     su = fresnel_sin(U, sul, suh);
  2051.     sw = fresnel_sin(W, swl, swh);
  2052.     cu = fresnel_cos(U, cul, cuh);
  2053.     cw = fresnel_cos(W, cwl, cwh);
  2054.  
  2055.     CD = cu - cw;
  2056.     CDL = cul - cwh;
  2057.     CDH = cuh - cwl;    
  2058.  
  2059.     SD = - su + sw;
  2060.     SDL = - suh + swl;
  2061.     SDH = - sul + swh;    
  2062.     
  2063.     res = hpc(l, R, T, CD, SD);
  2064.     hv = hpc(l, R, T, CDH, SDH);
  2065.     lv = hpc(l, R, T, CDL, SDL);
  2066.  
  2067.     return res;
  2068.  
  2069. }
  2070.  
  2071. ///* 
  2072.  
  2073.  
  2074.  
  2075.  
  2076. ///* fresnel_integrals.c         Matt Reilly 10/28/91 */
  2077. // converted for C++  2/17/94 pcw
  2078. //
  2079. ///*  approximation to Fresnel sine and Fresnel cosine needed to calculate
  2080. //    phase centers of horn 
  2081. //    
  2082. //*/
  2083. //
  2084. void fresnel_init()
  2085. {
  2086.     Pi = atan2(0.0, -1.0);
  2087.     Pi2 = Pi / 2.0;
  2088.     Pi2sq = Pi2 * Pi2;
  2089.     lib_init = 0;
  2090. }
  2091.  
  2092. double fresnel_f(double z)
  2093. //double z;
  2094. {
  2095.     /* from stegun and abramowitz pp 301 and 302. */
  2096.     double sum;
  2097.     
  2098.     sum = (1.0 + 0.926 * z) / (2.0 + 1.792 * z + 3.104 * z * z);
  2099.     
  2100.     return sum;
  2101. }
  2102.  
  2103. double fresnel_g(double z)
  2104. //double z;
  2105. {
  2106.     /* from stegun and abramowitz pp 301 and 302. */
  2107.     double sum;
  2108.     
  2109.     sum = 1.0 / (2.0 + 4.142 * z + 3.492 * z * z + 6.670 * z * z * z);
  2110.     
  2111.     return sum;
  2112. }
  2113.  
  2114. double fresnel_cos(double z, double &low, double &high)
  2115. //double z, *low, *high;
  2116. {
  2117. //    int n;   /* series index */
  2118.     double sum, x, f, g, c, s, fs1, fs2, gc1, gc2, sign;
  2119.          
  2120.     sign = 1.0;
  2121.     if(lib_init)   fresnel_init();
  2122.     
  2123.     if (z < 0) 
  2124.     {
  2125.         z = -z; 
  2126.     sign = - 1.0;
  2127.     }
  2128.     else sign = 1.0;
  2129.     
  2130.     x = Pi2 * z * z;
  2131.     f = fresnel_f(z);
  2132.     g = fresnel_g(z);
  2133.     c = cos(x);
  2134.     s = sin(x);
  2135.     
  2136.  
  2137.     
  2138.     sum = 0.5 + 
  2139.       f * s - 
  2140.       g * c;
  2141.  
  2142.     fs1 = (f + ERRMARGIN) * s;
  2143.     fs2 = (f - ERRMARGIN) * s;
  2144.     gc1 = (g + ERRMARGIN) * c;
  2145.     gc2 = (g - ERRMARGIN) * c;
  2146.  
  2147.     if(sign > 0)
  2148.     {
  2149.         low = (0.5 +  MIN(fs1, fs2) - MAX(gc1, gc2));
  2150.         high = (0.5 + MAX(fs1, fs2) - MIN(gc1, gc2));
  2151.     }
  2152.     else
  2153.     {
  2154.         low = -1.0 * (0.5 + MAX(fs1, fs2) - MIN(gc1, gc2));
  2155.         high = -1.0 * (0.5 +  MIN(fs1, fs2) - MAX(gc1, gc2));
  2156.     }
  2157.  
  2158.  
  2159.     return sum * sign;
  2160. }
  2161.  
  2162.  
  2163. double fresnel_sin(double z, double &low, double &high)
  2164. //double z, *low, *high;
  2165. {
  2166. //    int n;   /* series index */
  2167.      double sum, x, f, g, c, s, fc1, fc2, gs1, gs2, sign;
  2168.          
  2169.          
  2170.     if(lib_init)   fresnel_init();
  2171.     
  2172.  
  2173.     if (z < 0) 
  2174.     {
  2175.         z = -z; 
  2176.     sign = - 1.0;
  2177.     }
  2178.     else sign = 1.0;
  2179.  
  2180.     x = Pi2 * z * z;
  2181.      f = fresnel_f(z);
  2182.     g = fresnel_g(z);
  2183.     c = cos(x);
  2184.     s = sin(x);
  2185.     
  2186.     sum = 0.5 - 
  2187.       f * c - 
  2188.       g * s;
  2189.  
  2190.     fc1 = (f + ERRMARGIN) * c;
  2191.     fc2 = (f - ERRMARGIN) * c;
  2192.     gs1 = (g + ERRMARGIN) * s;
  2193.      gs2 = (g - ERRMARGIN) * s;
  2194.     
  2195.      if(sign > 0.0)
  2196.     {
  2197.         low = (0.5 - MAX(fc1, fc2) - MAX(gs1, gs2));
  2198.         high = (0.5 - MIN(fc1, fc2) - MIN(gs1, gs2));
  2199.     }
  2200.     else
  2201.     {
  2202.         low = -1.0 * (0.5 - MIN(fc1, fc2) - MIN(gs1, gs2));
  2203.         high = -1.0 * (0.5 - MAX(fc1, fc2) - MAX(gs1, gs2));
  2204.     }
  2205.  
  2206.     return sign * sum;
  2207. }
  2208. //
  2209.  
  2210.  
  2211.  
  2212.  
  2213.  
  2214.  
  2215.  
  2216.  
  2217.  
  2218.  
  2219. //forward declaration
  2220. double curve(double , int , double ); 
  2221.  
  2222.  
  2223. Lens::Lens() : Antenna()                   //constructor
  2224. {
  2225.     Lens_diam = 0.0;     
  2226.     spacing = 0.0  ;
  2227.     width_increase = 0.0;
  2228.     N = 0 ;
  2229.     BW_E_horn = 0.0 ;
  2230.     lens_focal_length = 0.0 ;     
  2231.     Gain_lens = 0.0 ;
  2232.     index = 0.0 ; 
  2233.     compensate = 0;
  2234.     step = 0.0;
  2235.     lens_to_horn = 0.0;
  2236. }    
  2237.  
  2238. void Lens::dimension()
  2239. //assumes that horn variables are available
  2240. {
  2241.     int bad = 1;
  2242.     while (bad >= 1 )
  2243.     {
  2244.     cout << "Enter approximate lens diameter in " 
  2245.              << units << ": ";
  2246.     cout.flush();
  2247.     cin >> Lens_diam  ;
  2248.         Lens_diam *= metric;
  2249.         
  2250.     cout << "Enter EXACT lens plate spacing in "
  2251.              << units << ": ";
  2252.     cout.flush();
  2253.     cin >> spacing ;
  2254.         spacing *= metric;
  2255.  
  2256.     if (spacing < (wavelength/2.0))
  2257.         {
  2258.         cout << " ERROR - lens plate spacing below cutoff \n";
  2259.             bad++ ;
  2260.             if (bad >= 3) break;
  2261.         }
  2262.         
  2263.     else if (spacing >= wavelength)
  2264.             {
  2265.           cout << " ERROR - lens plate spacing greater than wavelength \n";
  2266.               bad++ ;
  2267.               if (bad >= 3) break;
  2268.             }
  2269.             else bad = 0;
  2270.     }
  2271. }
  2272.  
  2273. void Lens::calculate()
  2274. {
  2275.  
  2276. //* make lens diameter an even number of spacings */
  2277.  
  2278.     N = (int)(Lens_diam /(2.0 * spacing)) ;
  2279.     if ( (Lens_diam - (2.0 * N * spacing)) > (spacing * 0.5 ))
  2280.         ++N;
  2281.  
  2282.     Lens_diam = 2.0 * N * spacing ;
  2283.     
  2284.  
  2285.     Gain_lens = (Lens_diam / E_aperture) * (Lens_diam / E_aperture) ;
  2286.         /* gain over bare horn */    
  2287.  
  2288.     Gain_lens =  10.0 * log10( Gain_lens );
  2289.  
  2290.     index = sqrt( 1.0 - ( wavelength / (2.0 * spacing)) *
  2291.             ( wavelength / (2.0 * spacing))) ;
  2292.         /* effective index of refraction */
  2293.  
  2294.     BW_E_horn = (56.0 / ( E_aperture / wavelength ))/crad ; /* Kraus, p. 380 */
  2295.         
  2296.     lens_focal_length = Lens_diam / (2.0 * tan(BW_E_horn / 2.0)) ; /* E-plane*/
  2297.         
  2298. /* NOTE: if the E and H focal planes are different, then we can compensate
  2299.          by making the lens have a different focal length in each plane;
  2300.          for now, it will be symmetrical using the E-plane focal length.
  2301.          The unknown is the distance from the horn to the lens, which is
  2302.          the lens focal length minus the horn_focal_point distance. */
  2303.         
  2304.      
  2305. //    cout << " This is an f over "
  2306. //         << (lens_focal_length/Lens_diam) << " lens \n";
  2307. //    cout << " using " << (2*N+1)
  2308. //         << " lens plates for an actual diameter of " 
  2309. //     << Lens_diam  << " mm \n\n";
  2310. //    cout << "\n";
  2311. //    cout << " Estimated gain of lens is " << Gain_lens
  2312. //     << " dB added to horn gain \n\n ":
  2313.  
  2314. }
  2315.  
  2316. void Lens::phasecheck()
  2317. {
  2318.  
  2319. /* get the phase centers and decide what to do about them */
  2320.  
  2321. //    Horn_E_phase_center = Phase_center('E', Ap_E_horn, guide_E);
  2322. //    Horn_H_phase_center = Phase_center('H', Ap_H_horn, guide_H);
  2323.  
  2324.     cout << "E-Plane phase center is " << E_phase_center
  2325.          << " wavelengths inside horn mouth\n";
  2326.     cout << "H-Plane phase center is " << H_phase_center
  2327.          << " wavelengths inside horn mouth\n\n";
  2328.     
  2329.  
  2330.     if (fabs(E_phase_center - H_phase_center)>0.062 /*wavelengths*/)
  2331.     {
  2332.         compensate = 1 ;
  2333.         cout << "     Phase correction may be in order,\n "
  2334.              << "     or you might want a different horn\n\n";
  2335.     }
  2336.     else compensate = 0 ;
  2337. }
  2338.  
  2339.  
  2340. //void Lens::plates()     // calculate radius of individual plates
  2341. //{
  2342. //    for (int i = 1 ; i <= N; i++ )
  2343. //    {
  2344. //        radius[i] = curve(radius[0],i) ;
  2345. //        radius_2[i] = curve(radius_2[0],i);
  2346. //        width_increase = radius[0] - radius[i] ;
  2347. //    }
  2348. //}
  2349.  
  2350. double curve(double radius, int i, double spacing)
  2351. {
  2352.     double theta ;       /* angle from axis */
  2353.     double radius_N ;    /* radius of plate N */
  2354.  
  2355.     theta = asin(( (double)i * spacing) / radius) ;
  2356.  
  2357.     radius_N = radius * cos(theta) ;
  2358.  
  2359.     return (radius_N) ;
  2360. }
  2361.  
  2362.  
  2363. void Lens::write_data(ostream& ostrm, int interactive)
  2364. {
  2365.     int i ;
  2366.      double FGHz = c / (wavelength * 1000000.0);
  2367.  
  2368. /* now a nice header */
  2369.  
  2370.     ostrm << "      Metal plate lens antenna for microwaves  \n\n";
  2371.     ostrm << "        ALL dimensions are in millimeters! \n\n" ;
  2372.  
  2373.     ostrm << "           ____________     \n";
  2374.     ostrm << "          |     E      |    \n";
  2375.     ostrm << "          |     ^ -->H |   waveguide  \n";
  2376.     ostrm << "          |     |      |    \n";
  2377.     ostrm << "           ------------     \n\n";
  2378.  
  2379.     ostrm << "  At a center frequency of "
  2380.       << setprecision(5) << FGHz << " GHz\n\n";
  2381.  
  2382.     ostrm << "  For a lens with a diameter of "
  2383.       << setprecision(5) << Lens_diam << " mm."
  2384.       << " and a plate spacing of "
  2385.       << setprecision(4) << spacing << " mm. \n\n";
  2386.  
  2387.     ostrm << "  Fed by a horn of axial length = "
  2388.       << setprecision(4) << axial_length << " mm, \n"
  2389.       << "      H-plane aperture = " << H_aperture << " mm \n"
  2390.       << "      E-plane aperture = " << E_aperture << " mm \n "
  2391.       << "      and a Gain of " << horn_gain
  2392.       << " dB over isotropic \n\n";
  2393.  
  2394.     ostrm << "   E-Plane phase center is " << setprecision(4)
  2395.       << E_phase_center << " wavelengths inside horn mouth\n";
  2396.     ostrm << "   H-Plane phase center is " << setprecision(4)
  2397.       << H_phase_center << " wavelengths inside horn mouth\n";
  2398.  
  2399.     lens_to_horn = lens_focal_length - (E_phase_center * wavelength);
  2400.  
  2401.     ostrm << "  Calculations for an f/" << setprecision(2)
  2402.       << (lens_focal_length/Lens_diam) ;
  2403.     ostrm << setprecision(4)
  2404.           << " lens with a focal length of " << lens_focal_length << " mm. \n"
  2405.       << "      providing an estimated gain of " << Gain_lens
  2406.       << " db over the horn\n\n"
  2407.       << "  Distance from horn mouth to center of lens curve is "
  2408.       << lens_to_horn << " mm.\n";
  2409.  
  2410. //    ostrm << "\n\n";
  2411.       if(interactive)
  2412.       {
  2413.         char pause;
  2414.         cout << "\n\nEnter D to display lens design dimensions: ";
  2415.         cout.flush();
  2416.         cin >> pause;
  2417.        }
  2418. /* design data */
  2419.  
  2420.     double radius[25];
  2421.     double radius_2[25];
  2422.     int SavedN;
  2423. /*    radius[0] = (index - 1.0) * lens_focal_length ; */ /* correct form */
  2424.     radius[0] = (1.0 - index ) * lens_focal_length ;      /* positive number */
  2425.  
  2426.     radius_2[0] = 2.0 * radius[0] ;
  2427.  
  2428.     SavedN = N;
  2429.     if (N > 24)
  2430.     {
  2431.     ostrm << "This is a pretty big lens, so only 50 plates calculated\n";
  2432.     N = 24;
  2433.     }
  2434.  
  2435.     for (i = 1 ; i <= N; i++ )
  2436.     {
  2437.     radius[i] = curve(radius[0],i,spacing) ;
  2438.     radius_2[i] = curve(radius_2[0],i,spacing);
  2439.     }
  2440.  
  2441.     if (!compensate)
  2442.     {
  2443.  
  2444.     ostrm << "\n  Radius of Curvature of lens plates starting from "
  2445.       << "center plate\n\n" ;
  2446.     ostrm << "   Plate  Single radius   double radius   plate width \n";
  2447.     ostrm << "   -----    -------         ---------      -------- \n\n";
  2448.     ostrm << setprecision(4)
  2449.       << "   ctr     " << radius[0] << " mm.     " << radius_2[0]
  2450.       << " mm.    min \n";
  2451.  
  2452.     for (i = 1 ; i <= N; i++ )
  2453.     {
  2454.         width_increase = radius[0] - radius[i] ;
  2455.  
  2456.         ostrm << setprecision(4)
  2457.         << "    " << i << "      " << radius[i] << " mm.     " << radius_2[i]
  2458.         << " mm.    min + " << width_increase << "\n";
  2459.     }
  2460.     }
  2461.  
  2462.     else            /* add column for compensation */
  2463.     {
  2464.  
  2465.     double c_focal_length = lens_focal_length +
  2466.              (H_phase_center - E_phase_center) * wavelength;
  2467.  
  2468.     double c_radius[25];
  2469.     c_radius[0] = (1.0 - index) * c_focal_length ;
  2470.  
  2471.     ostrm << "\n  Radius of Curvature of lens plates starting from "
  2472.       << "center plate\n" ;
  2473.     ostrm << "  with H-Plane phase compensation by shifting plate "
  2474.       << "centers\n";
  2475.     ostrm << "  of double-curved lens; positive shift is toward horn.\n\n";
  2476.  
  2477.     ostrm << "   Plate  Single radius   Double Radius   Plate Width"
  2478.       << "      Shift\n";
  2479.     ostrm << "   -----    -------         ---------     -----------"
  2480.       << "      ----- \n\n";
  2481.  
  2482.     ostrm << setprecision(4)
  2483.       << "   ctr     " << radius[0] << " mm.     " << radius_2[0]
  2484.       << " mm.       min \n";
  2485.  
  2486.     double shift [25];
  2487.  
  2488.     for (i = 1 ; i <= N; i++ )
  2489.     {
  2490.         width_increase = radius[0] - radius[i] ;
  2491.         c_radius[i] = curve(c_radius[0],i,spacing);
  2492.         shift[i] = radius[0] - radius[i] - (c_radius[0] - c_radius[i]);
  2493.  
  2494.     ostrm << setprecision(4)
  2495.       << "    " << i << "      " << radius[i] << " mm.     " << radius_2[i]
  2496.       << " mm.       min + " << width_increase << "   "
  2497.       << (shift[i]/2.0) << "\n";
  2498.     }
  2499.     }
  2500.  
  2501.     step = wavelength / ( 1.0 - index );
  2502.  
  2503.     if ( step < width_increase)
  2504.     ostrm << setprecision(4) << "\nFor a Zoned lens plate, "
  2505.       << "step distance = " << step <<" mm.\n\n";
  2506.  
  2507.     N = SavedN;
  2508. }
  2509.  
  2510. void Lens::crude_graphics(ostream& ostrm)
  2511. {
  2512. /* and a picture to help */
  2513.  
  2514.  
  2515. ostrm << "\n\n\n       ****** UNBELIEVABLY CRUDE GRAPHICS ******\n\n";
  2516.                                                                                 
  2517. ostrm << "               Single Curve        Double Curve \n\n";   
  2518.                                                                              
  2519. ostrm << "                       -----------         -------------\n";
  2520. ostrm << "                        ----------          ----------- \n";
  2521. ostrm << "        __               ---------    ^      --------- \n";
  2522. ostrm << "       |  |               --------    |       -------  \n";
  2523. ostrm << "       |  |    <          --------   H|       ---+---  \n";
  2524. ostrm << "       |  |    horn       --------    |       -------  \n";
  2525. ostrm << "        --               ---------           --------- \n";
  2526. ostrm << "       waveguide        ----------          -----------\n";
  2527. ostrm << "                       -----------         -------------\n";
  2528. ostrm << "                                                 +\n";
  2529. ostrm << "                                    centerline   + \n";
  2530. ostrm << "                                                 +\n";
  2531. ostrm << "                       -----------         -------------\n";
  2532. ostrm << "                        \\  LENS  |         \\   LENS    /\n";
  2533. ostrm << "       waveguide         \\ PLATE |    ^     \\  PLATE  /\n";
  2534. ostrm << "        _____             \\      |    |      \\       / \n";
  2535. ostrm << "       |     | <           )<--->|   E|       )<-+->(  \n";
  2536. ostrm << "        -----  horn       / min. |    |      /  min. \\ \n";
  2537. ostrm << "                      -->/ thick.|       -->/  thick. \\ \n";
  2538. ostrm << "                     /  /        |      /  /           \\ \n";
  2539. ostrm << "                    /  -----------     /   -------------\n";
  2540. ostrm << "                   /                  /                 \n";
  2541. ostrm << "                   Radius of curvature            \n\n\n";
  2542. }
  2543.     
  2544.  
  2545.  
  2546.  
  2547.  
  2548.  
  2549. // ****** end of ANTENNA.CPP file
  2550.  
  2551.  
  2552.  
  2553. // start of HDL_ANT.CPP 
  2554.  
  2555.  
  2556.  
  2557.  
  2558.  
  2559. //forward declarations
  2560. int KeyEvent(void);
  2561. void menu();
  2562. void pdish();
  2563. void odish();
  2564. void mlens();
  2565. void range();
  2566. void newhorn();
  2567. void oldhorn();
  2568. void feedhorn();
  2569. void nf_corr();
  2570. void noise_sky_ground();
  2571. void info();
  2572. void postinfo();
  2573. void english_units();
  2574.  
  2575. int main()
  2576. {
  2577.  
  2578.     Antenna start;
  2579.     start.banner(cout);
  2580.  
  2581.     cout << "\n HDL_ANT v2.1 - designs, makes calculations, and draws \n"
  2582.      << "            construction templates for microwave \n"
  2583.          << "            horn, lens, and parabolic dish antennas. \n\n"
  2584.      << " N1BWT 1996 \n\n";
  2585. //pause
  2586.     char pause;
  2587.     cout << "Hit <ENTER> key to continue";
  2588.     cout.flush();
  2589.     cin.setf(0,ios::skipws);
  2590.     cin >> pause;
  2591.     cin.setf(1,ios::skipws);
  2592.  
  2593.     int k = 0;
  2594.     menu();
  2595.     
  2596.     while ( (k = KeyEvent() ) != CTRL_C)
  2597.    {
  2598.     if (k)
  2599.     {
  2600.  
  2601.        // Mask out the key's scan code.
  2602.        k &= 0x00ff;
  2603.        char mode = (char)k;
  2604.  
  2605.        mode = toupper(mode);
  2606.         
  2607.         switch(mode)
  2608.             {
  2609.                 case 'H':   newhorn(); break;    
  2610.                 case 'E':   oldhorn(); break;
  2611.         case 'D':   pdish(); break;
  2612.                 case 'L':   mlens(); break;
  2613.         case 'R':   range(); break;
  2614.         case 'C':   nf_corr(); break;
  2615.         case 'I':   info(); break;
  2616.         case 'P':   postinfo(); break;
  2617.                 case 'U':   english_units(); break;
  2618.                 case 'Q':   return 0;
  2619. //new
  2620.                 case 'O':   odish(); break;
  2621.                 case 'F':   feedhorn(); break;
  2622.                 case 'N':   noise_sky_ground(); break;
  2623.                 
  2624.                 default: cout  << "Huh?"; break;
  2625.         }
  2626.  
  2627.             char pause;
  2628.             cout << "\n\nEnter C to continue: ";
  2629.         cout.flush();
  2630.         cin >> pause;
  2631.  
  2632.         menu();
  2633.         }             
  2634.     }
  2635.    return 0;
  2636. }
  2637.                  
  2638. void menu()             // just prints a menu to select from
  2639. {                
  2640.  
  2641. // clearscreen and reset xy
  2642. //        textmode(MONO);
  2643.     clrscr();
  2644.         gotoxy(1,1);
  2645.  
  2646.  
  2647.     cout << "\n"
  2648.       << "Enter first letter for selection \n\n"
  2649.           << "   Horn antenna design and template\n"
  2650.           << "   Existing horn antenna calculations\n"
  2651.           << "   Dish antenna calculations and template\n"
  2652.           << "   Lens antenna design\n"
  2653.           << "   Range design for antenna measurement\n"
  2654.           << "   Corrections for antenna measurements\n"
  2655.           << "   Information about HDL_ANT v2.1 program\n"
  2656.           << "   PostScript printing information\n"
  2657.           << "   Units: Metric [default] or English\n"
  2658.  
  2659.           << "\nNew***\n\n"
  2660.           << "   Offset dish calculations\n"
  2661.           << "   Feed horn design (from G3RPE curves)\n"
  2662.           << "   Noise Figure from sky and ground noise\n"
  2663.           <<"\n"
  2664.           
  2665.           << "   Quit\n";
  2666. }
  2667.  
  2668. int KeyEvent(void)
  2669. {
  2670.     // Check for key press.
  2671.      unsigned key = bioskey(1);
  2672.     
  2673.     // Get key if one is  available.
  2674.     if (key) key = bioskey(0);
  2675.     
  2676.     return key;
  2677.     
  2678. }
  2679.  
  2680.  
  2681. void pdish()
  2682. {
  2683.     cout << "\n\nPARABOLIC DISH ANTENNA CALCULATIONS AND TEMPLATE GENERATION\n\n";
  2684.     Dish d;
  2685.     d.get_freq();
  2686.     d.d_init();
  2687.     d.illumination();
  2688.     d.calc_gain();   
  2689.     char mode = 'n';
  2690.     cout << "\nDo you want to make a PostScript template [Yes or No]?  ";
  2691.     cout.flush();
  2692.     cin >> mode ;
  2693.     mode = toupper(mode);
  2694.  
  2695.     if (mode == 'Y') d.PS_template();
  2696. }
  2697.  
  2698. void odish()
  2699. {
  2700.     cout << "\n\nOFFSET PARABOLIC DISH ANTENNA CALCULATIONS \n\n";
  2701.     OffsetDish od;
  2702.     od.get_freq();
  2703.     od.offset_init();
  2704.     od.offset_illumination();
  2705.     od.offset_calc_gain();
  2706. }
  2707.  
  2708. void newhorn()
  2709. {
  2710.     cout << "\n\nDESIGN A HORN ANTENNA AND GENERATE A CONSTRUCTION TEMPLATE\n\n";
  2711.     char mode = 'Y';
  2712.     Horn a;
  2713.     a.get_freq();
  2714.     a.get_wg();
  2715.     if (a.bad_input() >= 3) goto end;
  2716.     a.lookup();
  2717.  
  2718.     while (mode == 'Y')
  2719.     {
  2720.         a.simple_gain();
  2721.         a.horn_angles();
  2722.         a.horn_calcgain();
  2723.         a.horn_phasecenters();
  2724.     a.write_data(cout,1);
  2725.  
  2726.         cout << "\nDo you want to change horn dimensions [Yes or No]?  ";
  2727.     cout.flush();
  2728.     cin >> mode ;
  2729.         mode = toupper(mode);
  2730.  
  2731.         if (mode == 'Y') a.horn_dimensions();
  2732.     }
  2733.  
  2734.     mode = 'n';
  2735.     cout << "\nDo you want to make a PostScript template [Yes or No]?  ";
  2736.     cout.flush();
  2737.     cin >> mode ;
  2738.     mode = toupper(mode);
  2739.  
  2740.     if (mode == 'Y')
  2741.     {
  2742.         a.coords();
  2743.         a.PS_template();
  2744.     }
  2745.  
  2746.     end: ;
  2747. }
  2748.  
  2749.  
  2750. void oldhorn()
  2751. {
  2752.     cout << "\n\nHORN ANTENNA CALCULATIONS AND CONSTRUCTION TEMPLATE "
  2753.          << "GENERATION\n\n";
  2754.     char mode = 'n';
  2755.     Horn a;
  2756.     a.get_freq();
  2757.     a.get_wg();
  2758.     if (a.bad_input() >= 3) goto end;
  2759.     a.horn_dimensions();
  2760.     a.check_aperture();
  2761.     if (a.bad_input() >= 3) goto end;
  2762.  
  2763.     a.simple_gain();
  2764.     a.horn_angles();
  2765.     a.horn_calcgain();
  2766.     a.horn_phasecenters();
  2767.     a.write_data(cout,1);
  2768.  
  2769.     cout << "\nDo you want to make a PostScript template [Yes or No]?  ";
  2770.     cout.flush();
  2771.     cin >> mode ;
  2772.     mode = toupper(mode);
  2773.  
  2774.     if (mode == 'Y')
  2775.     {
  2776.         a.coords();
  2777.         a.PS_template();
  2778.     }
  2779.  
  2780.     end: ;
  2781. }
  2782.  
  2783. void feedhorn()
  2784. {
  2785.     cout << "\n\nDESIGN A RECTANGULAR FEEDHORN FROM G3RPE CURVES \n"
  2786.          << " AND GENERATE A CONSTRUCTION TEMPLATE\n\n";
  2787.     char mode = 'Y';
  2788.     Horn fh;
  2789.     fh.get_freq();
  2790.     fh.get_wg();
  2791.     if (fh.bad_input() >= 3) goto end;
  2792.  
  2793.     double target_f_over_D;    
  2794.     cout << "\nEnter f/D to be illuminated: " ;
  2795.     cout.flush();
  2796.     cin >> target_f_over_D;
  2797.     
  2798.     fh.G3RPE_approximation(target_f_over_D);
  2799.     fh.check_aperture();
  2800.     if (fh.bad_input() >= 3) goto end;
  2801.  
  2802.     while (mode == 'Y')
  2803.     {
  2804.         fh.simple_gain();
  2805.         fh.horn_angles();
  2806.         fh.horn_calcgain();
  2807.         fh.horn_phasecenters();
  2808.     fh.write_data(cout,1);
  2809.  
  2810.         cout << "\nDo you want to change horn dimensions [Yes or No]?  ";
  2811.     cout.flush();
  2812.     cin >> mode ;
  2813.         mode = toupper(mode);
  2814.  
  2815.         if (mode == 'Y') fh.horn_dimensions();
  2816.     }
  2817.  
  2818.     mode = 'n';
  2819.     cout << "\nDo you want to make a PostScript template [Yes or No]?  ";
  2820.     cout.flush();
  2821.     cin >> mode ;
  2822.     mode = toupper(mode);
  2823.  
  2824.     if (mode == 'Y')
  2825.     {
  2826.         fh.coords();
  2827.         fh.PS_template();
  2828.     }
  2829.  
  2830.     end: ;
  2831. }
  2832.  
  2833.  
  2834. void mlens()
  2835. {
  2836.     cout << "\n\nMETAL PLATE LENS ANTENNA DESIGN\n\n";
  2837.     char mode = 'n';
  2838.     Lens m;
  2839.     m.get_freq();
  2840.     m.dimension();
  2841.     if (m.bad_input() >= 3) goto end;
  2842.     m.get_wg();
  2843.     m.horn_dimensions();
  2844.     m.horn_angles();
  2845.     m.horn_calcgain();
  2846.     m.calculate();
  2847.     m.horn_phasecenters();
  2848.     m.phasecheck();
  2849.     m.write_data(cout,1);
  2850.  
  2851. // set up output file if desired;
  2852.  
  2853.     cout << " Save this lens design to file (yes or NO) ";
  2854.     cout.flush();
  2855.     cin >> mode ;
  2856.     mode = toupper(mode);
  2857.  
  2858.     if (mode == 'Y')
  2859.     {
  2860.     char  outname[LINESIZE];
  2861.         cout << "\nEnter output filename: " ;
  2862.     cout.flush();
  2863.     cin >> outname ;
  2864.     
  2865.         ofstream ostrm(outname);
  2866.  
  2867.         m.banner(ostrm);
  2868.     m.write_data(ostrm,0);
  2869.         m.crude_graphics(ostrm);
  2870.     }
  2871.     end: ;
  2872. }
  2873.  
  2874. void range()
  2875. {
  2876.     cout << "\n\nANTENNA RANGE DESIGN CALCULATIONS\n\n";
  2877.     Antenna range;
  2878.     range.get_freq();
  2879.     range.range_calc();
  2880. }
  2881.  
  2882. void nf_corr()
  2883. {
  2884.     cout << "\n\n Correction of PANFI readings to Antenna Gain\n\n";
  2885.     Antenna c;
  2886.     c.get_freq();
  2887.     c.PANFI_corr();
  2888. }
  2889.  
  2890. void noise_sky_ground()
  2891. {
  2892.     cout << "\nTo calculate Noise Figure by comparing noise received \n"
  2893.          << "from cold sky and warm ground:\n";
  2894.     Antenna n;
  2895.     n.sun_gnd_NF();
  2896. }
  2897.  
  2898. void info()
  2899. {
  2900.     Antenna info;
  2901.     info.banner(cout);    
  2902.     info.info_listing(cout);
  2903.  
  2904. // set up output file if desired;
  2905.  
  2906.     char mode;
  2907.     cout << " \n\nWrite this information to file (Yes or No) ";
  2908.     cout.flush();
  2909.     cin >> mode ;
  2910.     mode = toupper(mode);
  2911.  
  2912.     if (mode == 'Y')
  2913.     {
  2914.     char outname[LINESIZE];
  2915.         cout << "\nEnter output filename: " ;
  2916.     cout.flush();
  2917.     cin >> outname ;
  2918.     
  2919.         ofstream ostrm(outname);
  2920.  
  2921.         info.banner(ostrm);
  2922.         info.info_listing(ostrm);
  2923.     }
  2924. }
  2925.  
  2926. void postinfo()
  2927. {
  2928.     Antenna pp;
  2929.     pp.post_print(cout);
  2930.  
  2931. // set up output file if desired;
  2932.  
  2933.     char mode;
  2934.     cout << " \n\nWrite this information to file (Yes or No) ";
  2935.     cout.flush();
  2936.     cin >> mode ;
  2937.     mode = toupper(mode);
  2938.  
  2939.     if (mode == 'Y')
  2940.     {
  2941.     char outname[LINESIZE];
  2942.         cout << "\nEnter output filename: " ;
  2943.     cout.flush();
  2944.     cin >> outname ;
  2945.     
  2946.         ofstream ostrm(outname);
  2947.  
  2948.         pp.post_print(ostrm);
  2949.     }
  2950. }
  2951.  
  2952. void english_units()
  2953. {
  2954.     char mode;
  2955.  
  2956.     cout << " \n\nCurrently using " << unit_type 
  2957.          << " units for dimensions\n";
  2958.     
  2959.     cout << " \n\nChange to alternate units(Yes or No) ";
  2960.     cout.flush();
  2961.     cin >> mode ;
  2962.     mode = toupper(mode);
  2963.  
  2964.     if (mode == 'Y')
  2965.     {
  2966.         if (metric == 1.0)  // change to English
  2967.         {
  2968.             metric = 25.4;
  2969.         units = "inches ";
  2970.         unit_type = "English";
  2971.     }
  2972.     else                // change to metric
  2973.     {
  2974.         metric = 1.0;
  2975.         units = " mm.  ";
  2976.             unit_type = "Metric ";
  2977.         }
  2978.     }
  2979. }
  2980.          
  2981.     
  2982.  
  2983. // end of HDL_ANT.CPP 
  2984.